From 3163b43fa48f7db6f45075f5f24ff130d33b22b2 Mon Sep 17 00:00:00 2001 From: taitep Date: Sat, 27 Sep 2025 21:43:10 +0200 Subject: [PATCH] base core state & instruction decoder --- src/consts.rs | 4 ++- src/core.rs | 58 ++++++++++++++++++++++++++++++++++++++++++++ src/decode.rs | 67 +++++++++++++++++++++++++++++++++++++++++++++++++++ src/lib.rs | 2 ++ 4 files changed, 130 insertions(+), 1 deletion(-) create mode 100644 src/core.rs create mode 100644 src/decode.rs diff --git a/src/consts.rs b/src/consts.rs index a3e33a2..1e52c92 100644 --- a/src/consts.rs +++ b/src/consts.rs @@ -3,5 +3,7 @@ pub type HWord = u16; pub type Word = u32; pub type DWord = u64; -pub type Reg = DWord; +pub type RegValue = DWord; pub type Addr = DWord; + +pub type RegId = u8; diff --git a/src/core.rs b/src/core.rs new file mode 100644 index 0000000..48668b5 --- /dev/null +++ b/src/core.rs @@ -0,0 +1,58 @@ +use crate::{ + consts::{Addr, RegId, RegValue}, + mem::MemConfig, +}; + +#[derive(PartialEq, Debug, Clone, Copy)] +pub enum ExecutionStatus { + Running, + Paused, + Halted, +} + +pub struct Core { + x_regs: [RegValue; 32], + pc: Addr, + mem: MemConfig, + exec_status: ExecutionStatus, +} + +impl Core { + pub fn new(mem: MemConfig) -> Self { + Self { + x_regs: [0; 32], + pc: 0, + mem, + exec_status: ExecutionStatus::Halted, + } + } + + pub fn reset(&mut self, pc: Addr) { + self.pc = pc; + self.exec_status = ExecutionStatus::Running; + } + + pub fn resume(&mut self) -> ExecutionStatus { + if self.exec_status == ExecutionStatus::Halted { + ExecutionStatus::Halted + } else { + self.exec_status = ExecutionStatus::Running; + ExecutionStatus::Running + } + } + + pub fn exec_status(&self) -> ExecutionStatus { + self.exec_status + } + + fn reg_read(&self, id: RegId) -> RegValue { + self.x_regs[id as usize] + } + + fn reg_write(&mut self, id: RegId, value: RegValue) { + if id == 0 { + return; + } + self.x_regs[id as usize] = value; + } +} diff --git a/src/decode.rs b/src/decode.rs new file mode 100644 index 0000000..0da4513 --- /dev/null +++ b/src/decode.rs @@ -0,0 +1,67 @@ +use crate::consts::{DWord, RegId, Word}; + +const MASK_REGISTER: Word = 0x1f; + +pub struct Instruction(pub Word); + +impl Instruction { + pub fn opcode(&self) -> u8 { + (self.0 & 0x7f) as u8 + } + + /// Returns the opcode of the instruction, with the last 2 bits stripped away, as they are always 0b11 in a non-compressed instruction + pub fn opcode_noncompressed(&self) -> u8 { + debug_assert_eq!(self.0 & 0b11, 0b11); + (self.0 >> 2 & 0x1f) as u8 + } + + pub fn rd(&self) -> RegId { + (self.0 >> 7 & MASK_REGISTER) as RegId + } + + pub fn funct3(&self) -> u8 { + (self.0 >> 12 & 0x7) as u8 + } + + pub fn rs1(&self) -> RegId { + (self.0 >> 15 & MASK_REGISTER) as RegId + } + + pub fn rs2(&self) -> RegId { + (self.0 >> 20 & MASK_REGISTER) as RegId + } + + pub fn funct7(&self) -> u8 { + (self.0 >> 25 & 0x7f) as u8 + } + + pub fn imm_i(&self) -> DWord { + (self.0 as i64 >> 20) as DWord + } + + pub fn imm_s(&self) -> DWord { + (self.0 as i64 >> (25 - 5) & (0x7f << 5)) as DWord | (self.0 >> 7 & 0b1111) as DWord + } + + pub fn imm_b(&self) -> DWord { + let imm_12 = ((self.0 & 0x8000_0000) as i32 as i64 >> (31 - 12)) as DWord; + let imm_10_5 = ((self.0 >> 25 & 0x3f) << 5) as DWord; + let imm_4_1 = ((self.0 >> 8 & 0xf) << 1) as DWord; + let imm_11 = ((self.0 >> 7 & 1) << 11) as DWord; + + imm_12 | imm_10_5 | imm_4_1 | imm_11 + } + + pub fn imm_u(&self) -> DWord { + (self.0 & 0xffff_f000) as i32 as i64 as DWord + } + + pub fn imm_j(&self) -> DWord { + let imm_20 = ((self.0 & 0x8000_0000) as i32 as i64 >> (31 - 20)) as DWord; + let imm_10_1 = ((self.0 >> 21 & 0x3ff) << 1) as DWord; + let imm_11 = ((self.0 >> 20 & 1) << 11) as DWord; + let imm_19_12 = ((self.0 >> 12 & 0xff) << 12) as DWord; + + imm_20 | imm_10_1 | imm_11 | imm_19_12 + } +} diff --git a/src/lib.rs b/src/lib.rs index 8484460..4020af3 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -1,2 +1,4 @@ mod consts; +pub mod core; +mod decode; pub mod mem;