diff options
| author | Nathan Lee <me@nwlee.tech> | 2026-06-10 22:27:19 -0500 |
|---|---|---|
| committer | Nathan Lee <me@nwlee.tech> | 2026-06-10 22:27:19 -0500 |
| commit | f94c087120bf2a241dda51d6311c565dd03b96be (patch) | |
| tree | 102d074b949bf5cd8caef386818c80153f254e4c /src | |
| parent | a37a07533fa9b8bd8962ca3c1aea082ae2548651 (diff) | |
move atomics into core.rs
Diffstat (limited to 'src')
| -rw-r--r-- | src/core.rs | 94 | ||||
| -rw-r--r-- | src/main.rs | 100 | ||||
| -rw-r--r-- | src/state.rs | 11 |
3 files changed, 118 insertions, 87 deletions
diff --git a/src/core.rs b/src/core.rs index 67a21de..3b59782 100644 --- a/src/core.rs +++ b/src/core.rs @@ -268,8 +268,98 @@ pub fn lui(state: &mut CpuState, rd: usize, imm: u32) { state.registers[rd] = imm << 12; } -pub fn auipc(state: &mut CpuState, pc: u32, rd: usize, imm: u32) { - state.registers[rd] = pc + (imm << 12); +pub fn lr_w(state: &mut CpuState, rd: usize, rs1: usize) { + let addr = state.registers[rs1] as usize; + state.registers[rd] = load_word(state, addr); + state.acquire_reservations(&[addr, addr + 1, addr + 2, addr + 3]); +} + +pub fn sc_w(state: &mut CpuState, rd: usize, rs1: usize, rs2: usize) { + let addr = state.registers[rs1] as usize; + if state.reservations.contains(&addr) { + store_word(state, addr, state.registers[rs2]); + state.registers[rd] = 0; + } else { + state.registers[rd] = 1; + } +} + +pub fn amoswap_w(state: &mut CpuState, rd: usize, rs1: usize, rs2: usize) { + let addr = state.registers[rs1] as usize; + let number: u32 = load_word(state, addr); + state.registers[rd] = number; + store_word(state, addr, state.registers[rs2]); +} + +pub fn amoadd_w(state: &mut CpuState, rd: usize, rs1: usize, rs2: usize) { + let addr = state.registers[rs1] as usize; + let number: u32 = load_word(state, addr); + state.registers[rd] = (number as i32 + state.registers[rs2] as i32) as u32; + store_word(state, addr, state.registers[rd]); +} + +pub fn amoand_w(state: &mut CpuState, rd: usize, rs1: usize, rs2: usize) { + let addr = state.registers[rs1] as usize; + let number: u32 = load_word(state, addr); + state.registers[rd] = number & state.registers[rs2]; + store_word(state, addr, state.registers[rd]); +} + +pub fn amoor_w(state: &mut CpuState, rd: usize, rs1: usize, rs2: usize) { + let addr = state.registers[rs1] as usize; + let number: u32 = load_word(state, addr); + state.registers[rd] = number | state.registers[rs2]; + store_word(state, addr, state.registers[rd]); +} + +pub fn amoxor_w(state: &mut CpuState, rd: usize, rs1: usize, rs2: usize) { + let addr = state.registers[rs1] as usize; + let number: u32 = load_word(state, addr); + state.registers[rd] = number ^ state.registers[rs2]; + store_word(state, addr, state.registers[rd]); +} + +pub fn amomax_w(state: &mut CpuState, rd: usize, rs1: usize, rs2: usize) { + let addr = state.registers[rs1] as usize; + let number: u32 = load_word(state, addr); + state.registers[rd] = std::cmp::max(number as i32, state.registers[rs2] as i32) as u32; + store_word(state, addr, state.registers[rd]); +} + +pub fn amomin_w(state: &mut CpuState, rd: usize, rs1: usize, rs2: usize) { + let addr = state.registers[rs1] as usize; + let number: u32 = load_word(state, addr); + state.registers[rd] = std::cmp::min(number as i32, state.registers[rs2] as i32) as u32; + store_word(state, addr, state.registers[rd]); +} + +pub fn amomaxu_w(state: &mut CpuState, rd: usize, rs1: usize, rs2: usize) { + let addr = state.registers[rs1] as usize; + let number: u32 = load_word(state, addr); + state.registers[rd] = std::cmp::max(number, state.registers[rs2]); + store_word(state, addr, state.registers[rd]); +} + +pub fn amominu_w(state: &mut CpuState, rd: usize, rs1: usize, rs2: usize) { + let addr = state.registers[rs1] as usize; + let number: u32 = load_word(state, addr); + state.registers[rd] = std::cmp::min(number, state.registers[rs2]); + store_word(state, addr, state.registers[rd]); +} + +fn load_word(state: &CpuState, addr: usize) -> u32 { + let slice = state.memory.read_multiple_bytes(addr, 4, 99).unwrap(); + u32::from_le_bytes(slice[0..4].try_into().unwrap()) +} +fn store_word(state: &mut CpuState, addr: usize, value: u32) { + state + .memory + .write_multiple_bytes(addr, &value.to_le_bytes(), 99) + .unwrap(); +} + +pub fn auipc(state: &mut CpuState, rd: usize, imm: u32) { + state.registers[rd] = state.pc + (imm << 12); } pub fn fmadd_s(state: &mut CpuState, rd: usize, rs1: usize, rs2: usize, rs3: usize) { diff --git a/src/main.rs b/src/main.rs index 965826e..48ce998 100644 --- a/src/main.rs +++ b/src/main.rs @@ -128,15 +128,15 @@ fn handle_instruction(state: &mut CpuState) { match f3 { 0 => { sb(state, rs1, rs2, imm); - release_reservations(state, &[addr]); + state.release_reservations(&[addr]); } 1 => { sh(state, rs1, rs2, imm); - release_reservations(state, &[addr, addr + 1]); + state.release_reservations(&[addr, addr + 1]); } 2 => { sw(state, rs1, rs2, imm); - release_reservations(state, &[addr, addr + 1, addr + 2, addr + 3]); + state.release_reservations(&[addr, addr + 1, addr + 2, addr + 3]); } _ => panic!("Illegal instruction: {:x}", word), }; @@ -195,7 +195,7 @@ fn handle_instruction(state: &mut CpuState) { 0b0010111 => { let imm = word >> 12; let rd = (word >> 7) & REGISTER_NAME_WIDTH; - auipc(state, *pc, rd as usize, imm); + auipc(state, rd as usize, imm); } 0b1110011 => { // ecall @@ -217,76 +217,17 @@ fn handle_instruction(state: &mut CpuState) { } match f5 { - 2 => { - let addr = state[rs1] as usize; - let number: u32 = load_word(&addr); - state[rd] = number; - acquire_reservations(reservations, &[addr, addr + 1, addr + 2, addr + 3]); - } // lr.w - 3 => { - let addr = state[rs1] as usize; - if (*reservations).contains(&addr) { - memory[addr..addr + 4].copy_from_slice(&state[rs2].to_le_bytes()); - state[rd] = 0; - } else { - state[rd] = 1; - } - } // sc.w - 1 => { - let addr = state[rs1] as usize; - let number: u32 = load_word(&addr); - state[rd] = number; - store_word(addr, state[rs2]); - } // amoswap.w - 0 => { - let addr = state[rs1] as usize; - let number: u32 = load_word(&addr); - state[rd] = (number as i32 + state[rs2] as i32) as u32; - store_word(addr, state[rd]); - } // amoadd.w - 12 => { - let addr = state[rs1] as usize; - let number: u32 = load_word(&addr); - state[rd] = number & state[rs2]; - store_word(addr, state[rd]); - } // amoand.w - 8 => { - let addr = state[rs1] as usize; - let number: u32 = load_word(&addr); - state[rd] = number | state[rs2]; - store_word(addr, state[rd]); - } // amoor.w - 4 => { - let addr = state[rs1] as usize; - let number: u32 = load_word(&addr); - state[rd] = number ^ state[rs2]; - store_word(addr, state[rd]); - } // amoxor.w - 20 => { - let addr = state[rs1] as usize; - let number: u32 = load_word(&addr); - state[rd] = std::cmp::max(number as i32, state[rs2] as i32) as u32; - store_word(addr, state[rd]); - } // amomax.w - 16 => { - let addr = state[rs1] as usize; - let number: u32 = load_word(&addr); - state[rd] = std::cmp::min(number as i32, state[rs2] as i32) as u32; - store_word(addr, state[rd]); - } // amomin.w - 28 => { - let addr = state[rs1] as usize; - let number: u32 = load_word(&addr); - state[rd] = std::cmp::max(number, state[rs2]); - store_word(addr, state[rd]); - } // amomaxu.w - 24 => { - let addr = state[rs1] as usize; - let number: u32 = load_word(&addr); - state[rd] = std::cmp::min(number, state[rs2]); - store_word(addr, state[rd]); - } // amomin.w - + 2 => lr_w(state, rd, rs1), + 3 => sc_w(state, rd, rs1, rs2), + 1 => amoswap_w(state, rd, rs1, rs2), + 0 => amoadd_w(state, rd, rs1, rs2), + 12 => amoand_w(state, rd, rs1, rs2), + 8 => amoor_w(state, rd, rs1, rs2), + 4 => amoxor_w(state, rd, rs1, rs2), + 20 => amomax_w(state, rd, rs1, rs2), + 16 => amomin_w(state, rd, rs1, rs2), + 28 => amomaxu_w(state, rd, rs1, rs2), + 24 => amominu_w(state, rd, rs1, rs2), _ => panic!("Illegal instruction: {:x}", word), } } @@ -380,15 +321,4 @@ fn handle_instruction(state: &mut CpuState) { } state.pc += 4; -} - -fn release_reservations(state: &mut CpuState, indices: &[usize]) { - for index in indices { - state.reservations.remove(&index); - } -} -fn acquire_reservations(state: &mut CpuState, indices: &[usize]) { - for index in indices { - state.reservations.insert(*index); - } }
\ No newline at end of file diff --git a/src/state.rs b/src/state.rs index dcb1959..adf6a5b 100644 --- a/src/state.rs +++ b/src/state.rs @@ -19,4 +19,15 @@ impl CpuState { reservations: HashSet::new() } } + + pub fn release_reservations(&mut self, indices: &[usize]) { + for index in indices { + self.reservations.remove(&index); + } + } + pub fn acquire_reservations(&mut self, indices: &[usize]) { + for index in indices { + self.reservations.insert(*index); + } + } }
\ No newline at end of file |
