finish base

This commit is contained in:
nora 2025-03-09 14:46:50 +01:00
parent 7026e5c1b8
commit b8d9f28059
6 changed files with 98 additions and 11 deletions

View file

@ -4,7 +4,6 @@ pub struct Elf {
pub content: Vec<u8>,
}
#[expect(dead_code)]
#[derive(Debug)]
pub struct Header {
pub e_entry: u32,
@ -19,7 +18,6 @@ pub struct Header {
pub e_shstrndx: u16,
}
#[expect(dead_code)]
#[derive(Debug)]
pub struct Phdr {
pub p_type: u32,

View file

@ -66,7 +66,6 @@ impl Memory {
}
#[derive(Debug)]
#[expect(dead_code)]
pub enum Error {
Trap(&'static str),
IllegalInstruction(InstCode, &'static str),
@ -109,7 +108,6 @@ impl IndexMut<Reg> for Emulator {
#[derive(Clone, Copy)]
pub struct Reg(pub u32);
#[expect(dead_code)]
impl Reg {
pub const RA: Reg = Reg(1);
pub const SP: Reg = Reg(2);
@ -307,6 +305,7 @@ impl Emulator {
}
Inst::Or { dest, src1, src2 } => self[dest] = self[src1] | self[src2],
Inst::And { dest, src1, src2 } => self[dest] = self[src1] & self[src2],
Inst::Fence { fence: _ } => { /* dont care */ }
Inst::Ecall => {
(self.ecall_handler)(&mut self.mem, &mut self.xreg)?;
}

View file

@ -2,6 +2,7 @@ use crate::emu::{Error, Reg};
use std::fmt::{Debug, Display};
use std::ops::RangeInclusive;
#[derive(Clone, Copy)]
pub enum Inst {
Lui { uimm: u32, dest: Reg },
Auipc { uimm: u32, dest: Reg },
@ -47,6 +48,8 @@ pub enum Inst {
Or { dest: Reg, src1: Reg, src2: Reg },
And { dest: Reg, src1: Reg, src2: Reg },
Fence { fence: Fence },
Ecall,
Ebreak,
@ -61,6 +64,23 @@ pub enum Inst {
Remu { dest: Reg, src1: Reg, src2: Reg },
}
#[derive(Clone, Copy)]
pub struct Fence {
pub fm: u32,
pub pred: FenceSet,
pub succ: FenceSet,
pub dest: Reg,
pub src: Reg,
}
#[derive(Clone, Copy, PartialEq, Eq)]
pub struct FenceSet {
pub device_input: bool,
pub device_output: bool,
pub memory_read: bool,
pub memory_write: bool,
}
impl Debug for Inst {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
Display::fmt(&self, f)
@ -162,6 +182,28 @@ impl Display for Inst {
Inst::Sra { dest, src1, src2 } => write!(f, "sra {dest}, {src1}, {src2}"),
Inst::Or { dest, src1, src2 } => write!(f, "or {dest}, {src1}, {src2}"),
Inst::And { dest, src1, src2 } => write!(f, "and {dest}, {src1}, {src2}"),
Inst::Fence { fence } => match fence.fm {
0b1000 => write!(f, "fence.TSO"),
0b0000
if fence.pred
== FenceSet {
device_input: false,
device_output: false,
memory_read: false,
memory_write: true,
}
&& fence.succ
== FenceSet {
device_input: false,
device_output: false,
memory_read: false,
memory_write: false,
} =>
{
write!(f, "pause")
}
_ => write!(f, "fence {},{}", fence.pred, fence.succ),
},
Inst::Ecall => write!(f, "ecall"),
Inst::Ebreak => write!(f, "ebreak"),
Inst::Mul { dest, src1, src2 } => write!(f, "mul {dest}, {src1}, {src2}"),
@ -176,6 +218,24 @@ impl Display for Inst {
}
}
impl Display for FenceSet {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
if self.device_input {
write!(f, "i")?;
}
if self.device_output {
write!(f, "o")?;
}
if self.memory_read {
write!(f, "r")?;
}
if self.memory_write {
write!(f, "w")?;
}
Ok(())
}
}
fn sign_extend(value: u32, size: u32) -> u32 {
assert!(size <= u32::BITS);
let sign = value >> (size - 1);
@ -439,6 +499,35 @@ impl Inst {
_ => return Err(Error::IllegalInstruction(code, "funct3/funct7")),
}
}
// MISC-MEM
0b0001111 => {
let fm = code.extract(28..=31);
let pred = FenceSet {
device_input: code.extract(27..=27) == 1,
device_output: code.extract(26..=26) == 1,
memory_read: code.extract(25..=25) == 1,
memory_write: code.extract(24..=24) == 1,
};
let succ = FenceSet {
device_input: code.extract(23..=23) == 1,
device_output: code.extract(22..=22) == 1,
memory_read: code.extract(21..=21) == 1,
memory_write: code.extract(20..=20) == 1,
};
match code.funct3() {
0b000 => Inst::Fence {
fence: Fence {
fm,
pred,
succ,
dest: code.rd(),
src: code.rs1(),
},
},
_ => return Err(Error::IllegalInstruction(code, "funct3")),
}
}
// SYSTEM
0b1110011 => {
if code.0 == 0b11000000000000000001000001110011 {

3
src/lib.rs Normal file
View file

@ -0,0 +1,3 @@
pub mod elf;
pub mod emu;
pub mod inst;

View file

@ -1,9 +1,8 @@
use emu::{Memory, Reg};
use eyre::{OptionExt, bail, eyre};
mod elf;
mod emu;
mod inst;
use rustv32i::{
elf,
emu::{self, Memory, Reg},
};
// 2 MiB
const MEMORY_SIZE: usize = 2 << 21;