fix stack alignment

Signed-off-by: Sean Cross <sean@xobs.io>
This commit is contained in:
2024-01-01 19:13:21 +08:00
parent f13d476a9f
commit 48206ee23c
4 changed files with 352 additions and 205 deletions

View File

@ -1,4 +1,4 @@
use std::sync::{Arc, RwLock, mpsc::Receiver};
use std::sync::{mpsc::Receiver, Arc, RwLock};
pub use super::mmu::Memory;
use super::mmu::{AddressingMode, Mmu};
@ -58,9 +58,9 @@ pub enum TickResult {
Ok,
ExitThread(u64),
PauseEmulation(Receiver<([i64; 8], Option<(Vec<u8>, u64)>)>),
CpuTrap(Trap),
}
/// Emulates a RISC-V CPU core
pub struct Cpu {
clock: u64,
@ -343,7 +343,6 @@ impl Cpu {
/// Runs program one cycle. Fetch, decode, and execution are completed in a cycle so far.
pub fn tick(&mut self) -> TickResult {
let instruction_address = self.pc;
match self.tick_operate() {
Ok(()) => {}
Err(Trap {
@ -358,7 +357,7 @@ impl Cpu {
}) => {
return TickResult::ExitThread(self.read_register(10) as u64);
}
Err(e) => self.handle_exception(e, instruction_address),
Err(e) => return TickResult::CpuTrap(e),
}
self.mmu.tick(&mut self.csr[CSR_MIP_ADDRESS as usize]);
self.handle_interrupt(self.pc);
@ -781,7 +780,7 @@ impl Cpu {
// println!("Fetching word from {:08x}...", self.pc);
self.mmu.fetch_word(self.pc).map_err(|e| {
self.pc = self.pc.wrapping_add(4); // @TODO: What if instruction is compressed?
// println!("Fetch error: {:x?}", e);
// println!("Fetch error: {:x?}", e);
e
})
}

View File

@ -1,171 +1,170 @@
/// Emulates main memory.
pub struct Memory {
/// Memory content
data: Vec<u64>
/// Memory content
data: Vec<u64>,
}
impl Memory {
/// Creates a new `Memory`
pub fn new() -> Self {
Memory {
data: vec![]
}
}
/// Creates a new `Memory`
pub fn new() -> Self {
Memory { data: vec![] }
}
/// Initializes memory content.
/// This method is expected to be called only once.
///
/// # Arguments
/// * `capacity`
pub fn init(&mut self, capacity: u64) {
for _i in 0..((capacity + 7) / 8) {
self.data.push(0);
}
}
/// Reads a byte from memory.
///
/// # Arguments
/// * `address`
pub fn read_byte(&self, address: u64) -> u8 {
let index = (address >> 3) as usize;
let pos = (address % 8) * 8;
(self.data[index] >> pos) as u8
}
/// Initializes memory content.
/// This method is expected to be called only once.
///
/// # Arguments
/// * `capacity`
pub fn init(&mut self, capacity: u64) {
for _i in 0..((capacity + 7) / 8) {
self.data.push(0);
}
}
/// Reads two bytes from memory.
///
/// # Arguments
/// * `address`
pub fn read_halfword(&self, address: u64) -> u16 {
if (address % 2) == 0 {
let index = (address >> 3) as usize;
let pos = (address % 8) * 8;
(self.data[index] >> pos) as u16
} else {
self.read_bytes(address, 2) as u16
}
}
/// Reads a byte from memory.
///
/// # Arguments
/// * `address`
pub fn read_byte(&self, address: u64) -> u8 {
let index = (address >> 3) as usize;
let pos = (address % 8) * 8;
(self.data[index] >> pos) as u8
}
/// Reads four bytes from memory.
///
/// # Arguments
/// * `address`
pub fn read_word(&self, address: u64) -> u32 {
if (address % 4) == 0 {
let index = (address >> 3) as usize;
let pos = (address % 8) * 8;
(self.data[index] >> pos) as u32
} else {
self.read_bytes(address, 4) as u32
}
}
/// Reads two bytes from memory.
///
/// # Arguments
/// * `address`
pub fn read_halfword(&self, address: u64) -> u16 {
if (address % 2) == 0 {
let index = (address >> 3) as usize;
let pos = (address % 8) * 8;
(self.data[index] >> pos) as u16
} else {
self.read_bytes(address, 2) as u16
}
}
/// Reads eight bytes from memory.
///
/// # Arguments
/// * `address`
pub fn read_doubleword(&self, address: u64) -> u64 {
if (address % 8) == 0 {
let index = (address >> 3) as usize;
self.data[index]
} else if (address % 4) == 0 {
(self.read_word(address) as u64) | ((self.read_word(address.wrapping_add(4)) as u64) << 4)
} else {
self.read_bytes(address, 8)
}
}
/// Reads four bytes from memory.
///
/// # Arguments
/// * `address`
pub fn read_word(&self, address: u64) -> u32 {
if (address % 4) == 0 {
let index = (address >> 3) as usize;
let pos = (address % 8) * 8;
(self.data[index] >> pos) as u32
} else {
self.read_bytes(address, 4) as u32
}
}
/// Reads multiple bytes from memory.
///
/// # Arguments
/// * `address`
/// * `width` up to eight
pub fn read_bytes(&self, address: u64, width: u64) -> u64 {
let mut data = 0;
for i in 0..width {
data |= (self.read_byte(address.wrapping_add(i)) as u64) << (i * 8);
}
data
}
/// Reads eight bytes from memory.
///
/// # Arguments
/// * `address`
pub fn read_doubleword(&self, address: u64) -> u64 {
if (address % 8) == 0 {
let index = (address >> 3) as usize;
self.data[index]
} else if (address % 4) == 0 {
(self.read_word(address) as u64)
| ((self.read_word(address.wrapping_add(4)) as u64) << 4)
} else {
self.read_bytes(address, 8)
}
}
/// Writes a byte to memory.
///
/// # Arguments
/// * `address`
/// * `value`
pub fn write_byte(&mut self, address: u64, value: u8) {
let index = (address >> 3) as usize;
let pos = (address % 8) * 8;
self.data[index] = (self.data[index] & !(0xff << pos)) | ((value as u64) << pos);
}
/// Reads multiple bytes from memory.
///
/// # Arguments
/// * `address`
/// * `width` up to eight
pub fn read_bytes(&self, address: u64, width: u64) -> u64 {
let mut data = 0;
for i in 0..width {
data |= (self.read_byte(address.wrapping_add(i)) as u64) << (i * 8);
}
data
}
/// Writes two bytes to memory.
///
/// # Arguments
/// * `address`
/// * `value`
pub fn write_halfword(&mut self, address: u64, value: u16) {
if (address % 2) == 0 {
let index = (address >> 3) as usize;
let pos = (address % 8) * 8;
self.data[index] = (self.data[index] & !(0xffff << pos)) | ((value as u64) << pos);
} else {
self.write_bytes(address, value as u64, 2);
}
}
/// Writes a byte to memory.
///
/// # Arguments
/// * `address`
/// * `value`
pub fn write_byte(&mut self, address: u64, value: u8) {
let index = (address >> 3) as usize;
let pos = (address % 8) * 8;
self.data[index] = (self.data[index] & !(0xff << pos)) | ((value as u64) << pos);
}
/// Writes four bytes to memory.
///
/// # Arguments
/// * `address`
/// * `value`
pub fn write_word(&mut self, address: u64, value: u32) {
if (address % 4) == 0 {
let index = (address >> 3) as usize;
let pos = (address % 8) * 8;
self.data[index] = (self.data[index] & !(0xffffffff << pos)) | ((value as u64) << pos);
} else {
self.write_bytes(address, value as u64, 4);
}
}
/// Writes two bytes to memory.
///
/// # Arguments
/// * `address`
/// * `value`
pub fn write_halfword(&mut self, address: u64, value: u16) {
if (address % 2) == 0 {
let index = (address >> 3) as usize;
let pos = (address % 8) * 8;
self.data[index] = (self.data[index] & !(0xffff << pos)) | ((value as u64) << pos);
} else {
self.write_bytes(address, value as u64, 2);
}
}
/// Writes eight bytes to memory.
///
/// # Arguments
/// * `address`
/// * `value`
pub fn write_doubleword(&mut self, address: u64, value: u64) {
if (address % 8) == 0 {
let index = (address >> 3) as usize;
self.data[index] = value;
} else if (address % 4) == 0 {
self.write_word(address, (value & 0xffffffff) as u32);
self.write_word(address.wrapping_add(4), (value >> 32) as u32);
} else {
self.write_bytes(address, value, 8);
}
}
/// Writes four bytes to memory.
///
/// # Arguments
/// * `address`
/// * `value`
pub fn write_word(&mut self, address: u64, value: u32) {
if (address % 4) == 0 {
let index = (address >> 3) as usize;
let pos = (address % 8) * 8;
self.data[index] = (self.data[index] & !(0xffffffff << pos)) | ((value as u64) << pos);
} else {
self.write_bytes(address, value as u64, 4);
}
}
/// Write multiple bytes to memory.
///
/// # Arguments
/// * `address`
/// * `value`
/// * `width` up to eight
pub fn write_bytes(&mut self, address: u64, value: u64, width: u64) {
for i in 0..width {
self.write_byte(address.wrapping_add(i), (value >> (i * 8)) as u8);
}
}
/// Writes eight bytes to memory.
///
/// # Arguments
/// * `address`
/// * `value`
pub fn write_doubleword(&mut self, address: u64, value: u64) {
if (address % 8) == 0 {
let index = (address >> 3) as usize;
self.data[index] = value;
} else if (address % 4) == 0 {
self.write_word(address, (value & 0xffffffff) as u32);
self.write_word(address.wrapping_add(4), (value >> 32) as u32);
} else {
self.write_bytes(address, value, 8);
}
}
/// Check if the address is valid memory address
///
/// # Arguments
/// * `address`
pub fn validate_address(&self, address: u64) -> bool {
(address as usize) < self.data.len()
}
/// Write multiple bytes to memory.
///
/// # Arguments
/// * `address`
/// * `value`
/// * `width` up to eight
pub fn write_bytes(&mut self, address: u64, value: u64, width: u64) {
for i in 0..width {
self.write_byte(address.wrapping_add(i), (value >> (i * 8)) as u8);
}
}
/// Check if the address is valid memory address
///
/// # Arguments
/// * `address`
pub fn validate_address(&self, address: u64) -> bool {
(address as usize) < self.data.len()
}
}
impl Default for Memory {