Skip to content

Commit

Permalink
Merge pull request #20 from Banyc/refactor/hard-coding
Browse files Browse the repository at this point in the history
fix hard-coding
  • Loading branch information
d0iasm authored Sep 7, 2022
2 parents d05be0a + 5c3eb7c commit 54f1020
Show file tree
Hide file tree
Showing 4 changed files with 109 additions and 63 deletions.
46 changes: 25 additions & 21 deletions src/cpu.rs
Original file line number Diff line number Diff line change
Expand Up @@ -327,13 +327,13 @@ impl Cpu {
match self.mode {
Mode::Machine => {
// Check if the MIE bit is enabled.
if (self.state.read(MSTATUS) >> 3) & 1 == 0 {
if self.state.read_mstatus(MSTATUS_MIE) == 0 {
return None;
}
}
Mode::Supervisor => {
// Check if the SIE bit is enabled.
if (self.state.read(SSTATUS) >> 1) & 1 == 0 {
if self.state.read_sstatus(XSTATUS_SIE) == 0 {
return None;
}
}
Expand Down Expand Up @@ -585,8 +585,8 @@ impl Cpu {
// 3.1.6.3 Memory Privilege in mstatus Register
// "When MPRV=1, load and store memory addresses are translated and protected, and
// endianness is applied, as though the current privilege mode were set to MPP."
if self.state.read_bit(MSTATUS, 17) == 1 {
self.mode = match self.state.read_bits(MSTATUS, 11..13) {
if self.state.read_mstatus(MSTATUS_MPRV) == 1 {
self.mode = match self.state.read_mstatus(MSTATUS_MPP) {
0b00 => Mode::User,
0b01 => Mode::Supervisor,
0b11 => Mode::Machine,
Expand All @@ -597,7 +597,7 @@ impl Cpu {
let p_addr = self.translate(v_addr, AccessType::Load)?;
let result = self.bus.read(p_addr, size);

if self.state.read_bit(MSTATUS, 17) == 1 {
if self.state.read_mstatus(MSTATUS_MPRV) == 1 {
self.mode = previous_mode;
}

Expand All @@ -612,8 +612,8 @@ impl Cpu {
// 3.1.6.3 Memory Privilege in mstatus Register
// "When MPRV=1, load and store memory addresses are translated and protected, and
// endianness is applied, as though the current privilege mode were set to MPP."
if self.state.read_bit(MSTATUS, 17) == 1 {
self.mode = match self.state.read_bits(MSTATUS, 11..13) {
if self.state.read_mstatus(MSTATUS_MPRV) == 1 {
self.mode = match self.state.read_mstatus(MSTATUS_MPP) {
0b00 => Mode::User,
0b01 => Mode::Supervisor,
0b11 => Mode::Machine,
Expand All @@ -630,7 +630,7 @@ impl Cpu {
let p_addr = self.translate(v_addr, AccessType::Store)?;
let result = self.bus.write(p_addr, value, size);

if self.state.read_bit(MSTATUS, 17) == 1 {
if self.state.read_mstatus(MSTATUS_MPRV) == 1 {
self.mode = previous_mode;
}

Expand Down Expand Up @@ -3374,11 +3374,11 @@ impl Cpu {

// Set the current privileged mode depending on a privious
// privilege mode for supervisor mode (SPP, 8).
self.mode = match self.state.read_bit(SSTATUS, 8) {
self.mode = match self.state.read_sstatus(XSTATUS_SPP) {
0b0 => Mode::User,
0b1 => {
// If SPP != M-mode, SRET also sets MPRV=0.
self.state.write_bit(MSTATUS, 17, 0);
self.state.write_mstatus(MSTATUS_MPRV, 0);
Mode::Supervisor
}
_ => Mode::Debug,
Expand All @@ -3387,14 +3387,16 @@ impl Cpu {
// Read a privious interrupt-enable bit for supervisor mode (SPIE,
// 5), and set a global interrupt-enable bit for supervisor mode
// (SIE, 1) to it.
self.state
.write_bit(SSTATUS, 1, self.state.read_bit(SSTATUS, 5));
self.state.write_sstatus(
XSTATUS_SIE,
self.state.read_sstatus(XSTATUS_SPIE),
);

// Set a privious interrupt-enable bit for supervisor mode (SPIE,
// 5) to 1.
self.state.write_bit(SSTATUS, 5, 1);
self.state.write_sstatus(XSTATUS_SPIE, 1);
// Set a privious privilege mode for supervisor mode (SPP, 8) to 0.
self.state.write_bit(SSTATUS, 8, 0);
self.state.write_sstatus(XSTATUS_SPP, 0);
}
(0x2, 0x18) => {
// mret
Expand All @@ -3414,15 +3416,15 @@ impl Cpu {

// Set the current privileged mode depending on a privious
// privilege mode for machine mode (MPP, 11..13).
self.mode = match self.state.read_bits(MSTATUS, 11..13) {
self.mode = match self.state.read_mstatus(MSTATUS_MPP) {
0b00 => {
// If MPP != M-mode, MRET also sets MPRV=0.
self.state.write_bit(MSTATUS, 17, 0);
self.state.write_mstatus(MSTATUS_MPRV, 0);
Mode::User
}
0b01 => {
// If MPP != M-mode, MRET also sets MPRV=0.
self.state.write_bit(MSTATUS, 17, 0);
self.state.write_mstatus(MSTATUS_MPRV, 0);
Mode::Supervisor
}
0b11 => Mode::Machine,
Expand All @@ -3432,16 +3434,18 @@ impl Cpu {
// Read a privious interrupt-enable bit for machine mode (MPIE, 7),
// and set a global interrupt-enable bit for machine mode (MIE, 3)
// to it.
self.state
.write_bit(MSTATUS, 3, self.state.read_bit(MSTATUS, 7));
self.state.write_mstatus(
MSTATUS_MIE,
self.state.read_mstatus(MSTATUS_MPIE),
);

// Set a privious interrupt-enable bit for machine mode (MPIE, 7)
// to 1.
self.state.write_bit(MSTATUS, 7, 1);
self.state.write_mstatus(MSTATUS_MPIE, 1);

// Set a privious privilege mode for machine mode (MPP, 11..13) to
// 0.
self.state.write_bits(MSTATUS, 11..13, 0b00);
self.state.write_mstatus(MSTATUS_MPP, Mode::User as u64);
}
(0x5, 0x8) => {
// wfi
Expand Down
82 changes: 61 additions & 21 deletions src/csr.rs
Original file line number Diff line number Diff line change
@@ -1,9 +1,10 @@
//! The csr module contains all the control and status registers.
use std::fmt;
use std::ops::{Bound, Range, RangeBounds};
use std::ops::{Bound, Range, RangeBounds, RangeInclusive};

pub type CsrAddress = u16;
pub type CsrFieldRange = RangeInclusive<usize>;

pub const MXLEN: usize = 64;
/// The number of CSRs. The field is 12 bits so the maximum kind of CSRs is 4096 (2**12).
Expand Down Expand Up @@ -70,26 +71,32 @@ pub const SIP: CsrAddress = 0x144;
pub const SATP: CsrAddress = 0x180;

// SSTATUS fields.
const SSTATUS_SIE: u64 = 0x2; // sstatus[1]
const SSTATUS_SPIE: u64 = 0x20; // sstatus[5]
const SSTATUS_UBE: u64 = 0x40; // sstatus[6]
const SSTATUS_SPP: u64 = 0x100; // sstatus[8]
const SSTATUS_FS: u64 = 0x6000; // sstatus[14:13]
const SSTATUS_XS: u64 = 0x18000; // sstatus[16:15]
const SSTATUS_SUM: u64 = 0x40000; // sstatus[18]
const SSTATUS_MXR: u64 = 0x80000; // sstatus[19]
const SSTATUS_UXL: u64 = 0x3_00000000; // sstatus[33:32]
const SSTATUS_SD: u64 = 0x80000000_00000000; // sstatus[63]
const SSTATUS_MASK: u64 = SSTATUS_SIE
| SSTATUS_SPIE
| SSTATUS_UBE
| SSTATUS_SPP
| SSTATUS_FS
| SSTATUS_XS
| SSTATUS_SUM
| SSTATUS_MXR
| SSTATUS_UXL
| SSTATUS_SD;
const SSTATUS_SIE_MASK: u64 = 0x2; // sstatus[1]
const SSTATUS_SPIE_MASK: u64 = 0x20; // sstatus[5]
const SSTATUS_UBE_MASK: u64 = 0x40; // sstatus[6]
const SSTATUS_SPP_MASK: u64 = 0x100; // sstatus[8]
const SSTATUS_FS_MASK: u64 = 0x6000; // sstatus[14:13]
const SSTATUS_XS_MASK: u64 = 0x18000; // sstatus[16:15]
const SSTATUS_SUM_MASK: u64 = 0x40000; // sstatus[18]
const SSTATUS_MXR_MASK: u64 = 0x80000; // sstatus[19]
const SSTATUS_UXL_MASK: u64 = 0x3_00000000; // sstatus[33:32]
const SSTATUS_SD_MASK: u64 = 0x80000000_00000000; // sstatus[63]
const SSTATUS_MASK: u64 = SSTATUS_SIE_MASK
| SSTATUS_SPIE_MASK
| SSTATUS_UBE_MASK
| SSTATUS_SPP_MASK
| SSTATUS_FS_MASK
| SSTATUS_XS_MASK
| SSTATUS_SUM_MASK
| SSTATUS_MXR_MASK
| SSTATUS_UXL_MASK
| SSTATUS_SD_MASK;
/// Global interrupt-enable bit for supervisor mode.
pub const XSTATUS_SIE: CsrFieldRange = 1..=1;
/// Previous interrupt-enable bit for supervisor mode.
pub const XSTATUS_SPIE: CsrFieldRange = 5..=5;
/// Previous privilege mode for supervisor mode.
pub const XSTATUS_SPP: CsrFieldRange = 8..=8;

/////////////////////////////////
// Machine-level CSR addresses //
Expand Down Expand Up @@ -138,6 +145,16 @@ const _PMPCFG0: CsrAddress = 0x3a0;
/// Physical memory protection address register.
const _PMPADDR0: CsrAddress = 0x3b0;

// MSTATUS fields.
/// Global interrupt-enable bit for machine mode.
pub const MSTATUS_MIE: CsrFieldRange = 3..=3;
/// Previous interrupt-enable bit for machine mode.
pub const MSTATUS_MPIE: CsrFieldRange = 7..=7;
/// Previous privilege mode for machine mode.
pub const MSTATUS_MPP: CsrFieldRange = 11..=12;
/// Modify privilege bit.
pub const MSTATUS_MPRV: CsrFieldRange = 17..=17;

// MIP fields.
/// Supervisor software interrupt.
pub const SSIP_BIT: u64 = 1 << 1;
Expand Down Expand Up @@ -318,12 +335,35 @@ impl State {
if (range.start >= MXLEN) | (range.end > MXLEN) | (range.start >= range.end) {
// TODO: ranse exception?
}
if (val >> (range.end - range.start)) != 0 {
// TODO: raise exception
}

let bitmask = (!0 << range.end) | !(!0 << range.start);
// Set bits.
self.write(addr, (self.read(addr) & bitmask) | (val << range.start))
}

/// Read bit(s) from a given field in the SSTATUS register.
pub fn read_sstatus(&self, range: CsrFieldRange) -> u64 {
self.read_bits(SSTATUS, range)
}

/// Read bit(s) from a given field in the MSTATUS register.
pub fn read_mstatus(&self, range: CsrFieldRange) -> u64 {
self.read_bits(MSTATUS, range)
}

/// Write bit(s) to a given field in the SSTATUS register.
pub fn write_sstatus(&mut self, range: CsrFieldRange, val: u64) {
self.write_bits(SSTATUS, range, val);
}

/// Write bit(s) to a given field in the MSTATUS register.
pub fn write_mstatus(&mut self, range: CsrFieldRange, val: u64) {
self.write_bits(MSTATUS, range, val);
}

/// Reset all the CSRs.
pub fn reset(&mut self) {
self.csrs = [0; CSR_SIZE];
Expand Down
18 changes: 9 additions & 9 deletions src/exception.rs
Original file line number Diff line number Diff line change
Expand Up @@ -157,15 +157,15 @@ impl Exception {
// Set a previous interrupt-enable bit for supervisor mode (SPIE, 5) to the value
// of a global interrupt-enable bit for supervisor mode (SIE, 1).
cpu.state
.write_bit(SSTATUS, 5, cpu.state.read_bit(SSTATUS, 1));
.write_sstatus(XSTATUS_SPIE, cpu.state.read_sstatus(XSTATUS_SIE));
// Set a global interrupt-enable bit for supervisor mode (SIE, 1) to 0.
cpu.state.write_bit(SSTATUS, 1, 0);
cpu.state.write_sstatus(XSTATUS_SIE, 0);
// 4.1.1 Supervisor Status Register (sstatus)
// "When a trap is taken, SPP is set to 0 if the trap originated from user mode, or
// 1 otherwise."
match previous_mode {
Mode::User => cpu.state.write_bit(SSTATUS, 8, 0),
_ => cpu.state.write_bit(SSTATUS, 8, 1),
Mode::User => cpu.state.write_sstatus(XSTATUS_SPP, 0),
_ => cpu.state.write_sstatus(XSTATUS_SPP, 1),
}
} else {
// Handle the trap in M-mode.
Expand Down Expand Up @@ -198,17 +198,17 @@ impl Exception {
// Set a previous interrupt-enable bit for machine mode (MPIE, 7) to the value
// of a global interrupt-enable bit for machine mode (MIE, 3).
cpu.state
.write_bit(MSTATUS, 7, cpu.state.read_bit(MSTATUS, 3));
.write_mstatus(MSTATUS_MPIE, cpu.state.read_mstatus(MSTATUS_MIE));
// Set a global interrupt-enable bit for machine mode (MIE, 3) to 0.
cpu.state.write_bit(MSTATUS, 3, 0);
cpu.state.write_mstatus(MSTATUS_MIE, 0);
// When a trap is taken from privilege mode y into privilege mode x, xPIE is set
// to the value of x IE; x IE is set to 0; and xPP is set to y.
match previous_mode {
Mode::User => cpu.state.write_bits(MSTATUS, 11..13, Mode::User as u64),
Mode::User => cpu.state.write_mstatus(MSTATUS_MPP, Mode::User as u64),
Mode::Supervisor => cpu
.state
.write_bits(MSTATUS, 11..13, Mode::Supervisor as u64),
Mode::Machine => cpu.state.write_bits(MSTATUS, 11..13, Mode::Machine as u64),
.write_mstatus(MSTATUS_MPP, Mode::Supervisor as u64),
Mode::Machine => cpu.state.write_mstatus(MSTATUS_MPP, Mode::Machine as u64),
_ => panic!("previous privilege mode is invalid"),
}
}
Expand Down
26 changes: 14 additions & 12 deletions src/interrupt.rs
Original file line number Diff line number Diff line change
Expand Up @@ -99,15 +99,15 @@ impl Interrupt {
// Set a privious interrupt-enable bit for supervisor mode (SPIE, 5) to the value
// of a global interrupt-enable bit for supervisor mode (SIE, 1).
cpu.state
.write_bit(SSTATUS, 5, cpu.state.read_bit(SSTATUS, 1));
.write_sstatus(XSTATUS_SPIE, cpu.state.read_sstatus(XSTATUS_SIE));
// Set a global interrupt-enable bit for supervisor mode (SIE, 1) to 0.
cpu.state.write_bit(SSTATUS, 1, 0);
cpu.state.write_sstatus(XSTATUS_SIE, 0);
// 4.1.1 Supervisor Status Register (sstatus)
// "When a trap is taken, SPP is set to 0 if the trap originated from user mode, or
// 1 otherwise."
match previous_mode {
Mode::User => cpu.state.write_bit(SSTATUS, 8, 0),
_ => cpu.state.write_bit(SSTATUS, 8, 1),
Mode::User => cpu.state.write_sstatus(XSTATUS_SPP, 0),
_ => cpu.state.write_sstatus(XSTATUS_SPP, 1),
}
} else {
// Handle the trap in M-mode.
Expand Down Expand Up @@ -147,18 +147,20 @@ impl Interrupt {
// instruction as described below. For other traps, mtval is set to zero."
cpu.state.write(MTVAL, 0);

// Set a privious interrupt-enable bit for supervisor mode (MPIE, 7) to the value
// of a global interrupt-enable bit for supervisor mode (MIE, 3).
// Set a previous interrupt-enable bit for machine mode (MPIE, 7) to the value
// of a global interrupt-enable bit for machine mode (MIE, 3).
cpu.state
.write_bit(MSTATUS, 7, cpu.state.read_bit(MSTATUS, 3));
// Set a global interrupt-enable bit for supervisor mode (MIE, 3) to 0.
cpu.state.write_bit(MSTATUS, 3, 0);
.write_mstatus(MSTATUS_MPIE, cpu.state.read_mstatus(MSTATUS_MIE));
// Set a global interrupt-enable bit for machine mode (MIE, 3) to 0.
cpu.state.write_mstatus(MSTATUS_MIE, 0);
// When a trap is taken from privilege mode y into privilege mode x, xPIE is set
// to the value of x IE; x IE is set to 0; and xPP is set to y.
match previous_mode {
Mode::User => cpu.state.write_bits(MSTATUS, 11..13, 0b00),
Mode::Supervisor => cpu.state.write_bits(MSTATUS, 11..13, 0b01),
Mode::Machine => cpu.state.write_bits(MSTATUS, 11..13, 0b11),
Mode::User => cpu.state.write_mstatus(MSTATUS_MPP, Mode::User as u64),
Mode::Supervisor => cpu
.state
.write_mstatus(MSTATUS_MPP, Mode::Supervisor as u64),
Mode::Machine => cpu.state.write_mstatus(MSTATUS_MPP, Mode::Machine as u64),
_ => panic!("previous privilege mode is invalid"),
}
}
Expand Down

0 comments on commit 54f1020

Please sign in to comment.