mirror of
https://github.com/Noratrieb/rustv32i.git
synced 2026-01-14 21:35:02 +01:00
This commit is contained in:
parent
f0c04f1466
commit
8d01c9f1d7
4 changed files with 290 additions and 67 deletions
108
src/emu.rs
108
src/emu.rs
|
|
@ -386,8 +386,33 @@ impl<XLEN: XLen> Emulator<XLEN> {
|
|||
Inst::Srli { imm, dest, src1 } => self[dest] = self[src1].unsigned_shr(imm.as_u32()),
|
||||
Inst::Srai { imm, dest, src1 } => self[dest] = self[src1].signed_shr(imm.as_u32()),
|
||||
Inst::Add { dest, src1, src2 } => self[dest] = self[src1].add(self[src2]),
|
||||
Inst::AddW { dest, src1, src2 } => {
|
||||
self[dest] = XLEN::switch2(
|
||||
self[src1],
|
||||
self[src2],
|
||||
|_, _| unreachable!(),
|
||||
|a, b| (a as u32).add(b as u32) as i32 as i64 as u64,
|
||||
);
|
||||
}
|
||||
Inst::Sub { dest, src1, src2 } => self[dest] = self[src1].sub(self[src2]),
|
||||
Inst::Sll { dest, src1, src2 } => self[dest] = self[src1].shl(self[src2].truncate32()),
|
||||
Inst::SubW { dest, src1, src2 } => {
|
||||
self[dest] = XLEN::switch2(
|
||||
self[src1],
|
||||
self[src2],
|
||||
|_, _| unreachable!(),
|
||||
|a, b| (a as u32).sub(b as u32) as i32 as i64 as u64,
|
||||
);
|
||||
}
|
||||
Inst::Sll { dest, src1, src2 } => {
|
||||
self[dest] = self[src1].shl(self[src2].truncate32());
|
||||
}
|
||||
Inst::SllW { dest, src1, src2 } => {
|
||||
self[dest] = XLEN::switch(
|
||||
self[src1],
|
||||
|_| unreachable!(),
|
||||
|a| (a as u32).shl(self[src2].truncate32()) as i32 as i64 as u64,
|
||||
);
|
||||
}
|
||||
Inst::Slt { dest, src1, src2 } => {
|
||||
self[dest] = XLEN::from_bool(self[src1].signed_lt(self[src2]));
|
||||
}
|
||||
|
|
@ -398,9 +423,23 @@ impl<XLEN: XLen> Emulator<XLEN> {
|
|||
Inst::Srl { dest, src1, src2 } => {
|
||||
self[dest] = self[src1].unsigned_shr(self[src2].truncate32())
|
||||
}
|
||||
Inst::SrlW { dest, src1, src2 } => {
|
||||
self[dest] = XLEN::switch(
|
||||
self[src1],
|
||||
|_| unreachable!(),
|
||||
|a| (a as u32).unsigned_shr(self[src2].truncate32()) as i32 as i64 as u64,
|
||||
);
|
||||
}
|
||||
Inst::Sra { dest, src1, src2 } => {
|
||||
self[dest] = self[src1].signed_shr(self[src2].truncate32())
|
||||
}
|
||||
Inst::SraW { dest, src1, src2 } => {
|
||||
self[dest] = XLEN::switch(
|
||||
self[src1],
|
||||
|_| unreachable!(),
|
||||
|a| (a as u32).unsigned_shr(self[src2].truncate32()) as i32 as i64 as u64,
|
||||
);
|
||||
}
|
||||
Inst::Or { dest, src1, src2 } => self[dest] = self[src1].or(self[src2]),
|
||||
Inst::And { dest, src1, src2 } => self[dest] = self[src1].and(self[src2]),
|
||||
Inst::Fence { fence: _ } => { /* dont care */ }
|
||||
|
|
@ -502,7 +541,40 @@ impl<XLEN: XLen> Emulator<XLEN> {
|
|||
}
|
||||
self.reservation_set = None;
|
||||
}
|
||||
_ => return Err(Status::UnsupportedInst(inst)),
|
||||
Inst::AddiW { imm, dest, src1 } => {
|
||||
self[dest] = XLEN::switch(
|
||||
self[src1],
|
||||
|_| unreachable!(),
|
||||
|src| ((src as u32).wrapping_add(imm.as_u32())) as i32 as i64 as u64,
|
||||
);
|
||||
}
|
||||
Inst::SlliW { imm, dest, src1 } => {
|
||||
self[dest] = XLEN::switch(
|
||||
self[src1],
|
||||
|_| unreachable!(),
|
||||
|src| ((src as u32).shl(imm.as_u32())) as u64,
|
||||
);
|
||||
}
|
||||
Inst::SrliW { imm, dest, src1 } => {
|
||||
self[dest] = XLEN::switch(
|
||||
self[src1],
|
||||
|_| unreachable!(),
|
||||
|src| ((src as u32).unsigned_shr(imm.as_u32())) as u64,
|
||||
);
|
||||
}
|
||||
Inst::SraiW { imm, dest, src1 } => {
|
||||
self[dest] = XLEN::switch(
|
||||
self[src1],
|
||||
|_| unreachable!(),
|
||||
|src| ((src as u32).signed_shr(imm.as_u32())) as u64,
|
||||
);
|
||||
}
|
||||
Inst::MulW { dest, src1, src2 } => todo!(),
|
||||
Inst::DivW { dest, src1, src2 } => todo!(),
|
||||
Inst::DivuW { dest, src1, src2 } => todo!(),
|
||||
Inst::RemW { dest, src1, src2 } => todo!(),
|
||||
Inst::RemuW { dest, src1, src2 } => todo!(),
|
||||
_ => todo!(),
|
||||
}
|
||||
|
||||
if !jumped {
|
||||
|
|
@ -676,7 +748,7 @@ impl<XLEN: XLen> Emulator<XLEN> {
|
|||
}
|
||||
}
|
||||
|
||||
pub trait XLen: Copy + PartialEq + Eq {
|
||||
pub trait XLen: Copy + PartialEq + Eq + Debug {
|
||||
type Signed;
|
||||
type NextUnsigned;
|
||||
type NextSigned;
|
||||
|
|
@ -687,7 +759,15 @@ pub trait XLen: Copy + PartialEq + Eq {
|
|||
const SIGNED_MIN: Self;
|
||||
const MAX: Self;
|
||||
|
||||
fn switch<R>(self, on_32: impl FnOnce(u32) -> R, on_64: impl FnOnce(u64) -> R) -> R;
|
||||
const IS_64: bool = matches!(Self::XLEN, rvdc::Xlen::Rv64);
|
||||
|
||||
fn switch(self, on_32: impl FnOnce(u32) -> u32, on_64: impl FnOnce(u64) -> u64) -> Self;
|
||||
fn switch2(
|
||||
self,
|
||||
other: Self,
|
||||
on_32: impl FnOnce(u32, u32) -> u32,
|
||||
on_64: impl FnOnce(u64, u64) -> u64,
|
||||
) -> Self;
|
||||
|
||||
fn from_bool(v: bool) -> Self {
|
||||
Self::from_32_z(v as u32)
|
||||
|
|
@ -839,9 +919,17 @@ impl XLen for u32 {
|
|||
|
||||
const XLEN: rvdc::Xlen = rvdc::Xlen::Rv32;
|
||||
|
||||
fn switch<R>(self, on_32: impl FnOnce(u32) -> R, _: impl FnOnce(u64) -> R) -> R {
|
||||
fn switch(self, on_32: impl FnOnce(u32) -> u32, _: impl FnOnce(u64) -> u64) -> Self {
|
||||
on_32(self)
|
||||
}
|
||||
fn switch2(
|
||||
self,
|
||||
other: Self,
|
||||
on_32: impl FnOnce(u32, u32) -> u32,
|
||||
_: impl FnOnce(u64, u64) -> u64,
|
||||
) -> Self {
|
||||
on_32(self, other)
|
||||
}
|
||||
|
||||
fn from_32_s(v: u32) -> Self {
|
||||
v
|
||||
|
|
@ -863,9 +951,17 @@ impl XLen for u64 {
|
|||
|
||||
const XLEN: rvdc::Xlen = rvdc::Xlen::Rv64;
|
||||
|
||||
fn switch<R>(self, _: impl FnOnce(u32) -> R, on_64: impl FnOnce(u64) -> R) -> R {
|
||||
fn switch(self, _: impl FnOnce(u32) -> u32, on_64: impl FnOnce(u64) -> u64) -> Self {
|
||||
on_64(self)
|
||||
}
|
||||
fn switch2(
|
||||
self,
|
||||
other: Self,
|
||||
_: impl FnOnce(u32, u32) -> u32,
|
||||
on_64: impl FnOnce(u64, u64) -> u64,
|
||||
) -> Self {
|
||||
on_64(self, other)
|
||||
}
|
||||
|
||||
fn from_32_s(v: u32) -> Self {
|
||||
v as i32 as i64 as u64
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue