summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/core.rs30
-rw-r--r--src/main.rs31
-rw-r--r--src/state.rs3
3 files changed, 56 insertions, 8 deletions
diff --git a/src/core.rs b/src/core.rs
index 9e8e8dd..60d720b 100644
--- a/src/core.rs
+++ b/src/core.rs
@@ -520,3 +520,33 @@ pub fn fclass_s(state: &mut CpuState, rd: usize, rs1: usize) {
}
}
}
+
+pub fn csrrw(state: &mut CpuState, rd: usize, rs1: usize, csr: usize) {
+ state.registers[rd] = state.csr[csr];
+ state.csr[csr] = state.registers[rs1];
+}
+
+pub fn csrrwi(state: &mut CpuState, rd: usize, imm: u32, csr: usize) {
+ state.registers[rd] = state.csr[csr];
+ state.csr[csr] = imm;
+}
+
+pub fn csrrc(state: &mut CpuState, rd: usize, rs1: usize, csr: usize) {
+ state.registers[rd] = state.csr[csr];
+ state.csr[csr] &= !state.registers[rs1];
+}
+
+pub fn csrrci(state: &mut CpuState, rd: usize, imm: u32, csr: usize) {
+ state.registers[rd] = state.csr[csr];
+ state.csr[csr] &= !imm;
+}
+
+pub fn csrrs(state: &mut CpuState, rd: usize, rs1: usize, csr: usize) {
+ state.registers[rd] = state.csr[csr];
+ state.csr[csr] |= state.registers[rs1];
+}
+
+pub fn csrrsi(state: &mut CpuState, rd: usize, imm: u32, csr: usize) {
+ state.registers[rd] = state.csr[csr];
+ state.csr[csr] |= imm;
+} \ No newline at end of file
diff --git a/src/main.rs b/src/main.rs
index 3d8008d..20dde55 100644
--- a/src/main.rs
+++ b/src/main.rs
@@ -134,8 +134,6 @@ fn handle_instruction(state: &mut CpuState) {
let imm = ((((imm_high << 5) | imm_low) as i32) << 20 >> 20) as u32;
- let addr = (state.registers[rs1] + imm) as usize;
-
match f3 {
0 => sb(state, rs1, rs2, imm),
1 => sh(state, rs1, rs2, imm),
@@ -200,11 +198,30 @@ fn handle_instruction(state: &mut CpuState) {
auipc(state, rd as usize, imm);
}
0b1110011 => {
- // ecall
- eprintln!(
- "TRAP! syscall {} with gp state {:?}",
- state.registers[17], pc
- );
+ let imm = word >> 20;
+ let rd = ((word >> 7) & REGISTER_NAME_WIDTH) as usize;
+ let rs1 = ((word >> 15) & REGISTER_NAME_WIDTH) as usize;
+ let f3 = (word >> 12) & 0b111;
+
+ match f3 {
+ 0 => {
+ eprintln!(
+ "TRAP! syscall {} with gp state {:?}",
+ state.registers[17], pc
+ );
+
+ // todo: trap to CSR 0x305
+ } // ecall
+ 1 => csrrw(state, rd, rs1, imm as usize),
+ 2 => csrrs(state, rd, rs1, imm as usize),
+ 3 => csrrc(state, rd, rs1, imm as usize),
+ 5 => csrrwi(state, rd, rs1 as u32, imm as usize),
+ 6 => csrrsi(state, rd, rs1 as u32, imm as usize),
+ 7 => csrrci(state, rd, rs1 as u32, imm as usize),
+
+ _ => panic!("Illegal instruction: {:x}", word),
+ }
+
} // ecall (ebreak not implemented)
0b0101111 => {
let f5 = word >> 27;
diff --git a/src/state.rs b/src/state.rs
index 6b1fb81..d4690bb 100644
--- a/src/state.rs
+++ b/src/state.rs
@@ -1,10 +1,10 @@
use crate::mem::Memory;
-use std::collections::HashSet;
pub struct CpuState {
pub memory: Memory,
pub registers: [u32; 32],
pub f_registers: [f32; 32],
+ pub csr: [u32; 4096],
pub pc: u32,
pub reserved_addr: Option<usize>,
}
@@ -15,6 +15,7 @@ impl CpuState {
memory,
registers: [0u32; 32],
f_registers: [0f32; 32],
+ csr: [0u32; 4096],
pc: 0,
reserved_addr: None,
}