aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/isa/funct3.rs12
-rw-r--r--src/simulator.rs116
2 files changed, 76 insertions, 52 deletions
diff --git a/src/isa/funct3.rs b/src/isa/funct3.rs
index 94f2f41..7cb3c5d 100644
--- a/src/isa/funct3.rs
+++ b/src/isa/funct3.rs
@@ -39,6 +39,12 @@ pub const BGE: u32 = 0b101;
pub const BLTU: u32 = 0b110;
pub const BGEU: u32 = 0b111;
-pub const LW: u32 = 0x2;
-
-pub const SW: u32 = 0x2;
+pub const LB: u32 = 0b000;
+pub const LH: u32 = 0b001;
+pub const LW: u32 = 0b010;
+pub const LBU: u32 = 0b100;
+pub const LHU: u32 = 0b101;
+
+pub const SB: u32 = 0b000;
+pub const SH: u32 = 0b001;
+pub const SW: u32 = 0b010;
diff --git a/src/simulator.rs b/src/simulator.rs
index 4feb1c0..006244a 100644
--- a/src/simulator.rs
+++ b/src/simulator.rs
@@ -280,61 +280,79 @@ impl<'a> Core<'a> {
self.registers.write_word(inst.rd(), value);
}
},
- isa::opcodes::LOAD => match inst.funct3() {
- isa::funct3::LW => {
- let imm = inst.i_imm();
- let base = self.registers.read_word(inst.rs1());
- let address = ((base as isa::SignedWord) + imm) as isa::Address;
- let address = self.mmu.translate(address);
+ isa::opcodes::LOAD => {
+ let imm = inst.i_imm();
+ let base = self.registers.read_word(inst.rs1());
+ let address = ((base as isa::SignedWord) + imm) as isa::Address;
+ let address = self.mmu.translate(address);
- let result = self.cache.borrow_mut().read_word(address);
- match result {
- Ok(value) => self.registers.write_word(inst.rd(), value),
- Err(MemoryError::CacheMiss { stall_cycles }) => {
- self.stall = stall_cycles;
- return;
- },
- Err(MemoryError::InvalidAddress) => {
- self.trap(Trap::IllegalRead {
- address: pc,
- instruction: inst,
- memory_address: address,
- });
- }
- }
- },
- _ => {
- panic!("Invalid load funct3code: 0x{:x}", inst.funct3());
+ let result = match inst.funct3() {
+ isa::funct3::LB =>
+ self.cache.borrow_mut()
+ .read_byte(address)
+ .map(|b| (b as isa::SignedByte) as isa::Word),
+ isa::funct3::LH =>
+ panic!("{:x}: Unimplemented LH"),
+ isa::funct3::LW =>
+ self.cache.borrow_mut().read_word(address),
+ isa::funct3::LBU =>
+ self.cache.borrow_mut()
+ .read_byte(address)
+ .map(|b| b as isa::Word),
+ isa::funct3::LHU =>
+ panic!("{:x}: Unimplemented LHU"),
+ _ => panic!("{:x}: Invalid load funct3code: 0x{:x}",
+ pc, inst.funct3()),
+ };
+
+ match result {
+ Ok(value) => self.registers.write_word(inst.rd(), value),
+ Err(MemoryError::CacheMiss { stall_cycles }) => {
+ self.stall = stall_cycles;
+ return; // don't increment PC
+ },
+ Err(MemoryError::InvalidAddress) => {
+ self.trap(Trap::IllegalRead {
+ address: pc,
+ instruction: inst,
+ memory_address: address,
+ });
+ },
}
},
- isa::opcodes::STORE => match inst.funct3() {
- isa::funct3::SW => {
- let imm = inst.s_imm();
- let base = self.registers.read_word(inst.rs1());
- let val = self.registers.read_word(inst.rs2());
- let address = ((base as isa::SignedWord) + imm) as isa::Address;
- let address = self.mmu.translate(address);
+ isa::opcodes::STORE => {
+ let imm = inst.s_imm();
+ let base = self.registers.read_word(inst.rs1());
+ let val = self.registers.read_word(inst.rs2());
+ let address = ((base as isa::SignedWord) + imm) as isa::Address;
+ let address = self.mmu.translate(address);
- let result = self.cache.borrow_mut().write_word(address, val);
- match result {
- Ok(()) => (),
- Err(MemoryError::CacheMiss { stall_cycles }) => {
- self.stall = stall_cycles - 1;
- return;
- },
- Err(MemoryError::InvalidAddress) => {
- self.trap(Trap::IllegalWrite {
- address: pc,
- instruction: inst,
- memory_address: address,
- memory_value: val,
- })
- }
+ let result = match inst.funct3() {
+ isa::funct3::SB =>
+ self.cache.borrow_mut().write_byte(address, val as u8),
+ isa::funct3::SH =>
+ panic!("PC {:x}: Unimplemented SH"),
+ isa::funct3::SW =>
+ self.cache.borrow_mut().write_word(address, val),
+ _ => panic!("PC {:x}: Invalid store funct3code: 0x{:x}",
+ pc, inst.funct3()),
+ };
+
+ match result {
+ Ok(()) => (),
+ Err(MemoryError::CacheMiss { stall_cycles }) => {
+ self.stall = stall_cycles;
+ return; // don't increment PC
+ },
+ Err(MemoryError::InvalidAddress) => {
+ self.trap(Trap::IllegalWrite {
+ address: pc,
+ instruction: inst,
+ memory_address: address,
+ memory_value: val,
+ })
}
}
- _ => {
- panic!("Invalid store funct3code: 0x{:x}", inst.funct3());
- }
},
isa::opcodes::SYSTEM => match inst.i_imm() {
0x0 => {