diff --git a/src/simulator/error.rs b/src/simulator/error.rs index d6ea783..a61dac2 100644 --- a/src/simulator/error.rs +++ b/src/simulator/error.rs @@ -24,6 +24,11 @@ pub struct MachineError { message: String } +pub enum MachineOk { + Ok, + Shutdown +} + /// This impl allows this MachineError to be formatted into an empty format. /// /// ``` diff --git a/src/simulator/machine.rs b/src/simulator/machine.rs index d544dc3..6f07fa7 100644 --- a/src/simulator/machine.rs +++ b/src/simulator/machine.rs @@ -27,6 +27,8 @@ use crate::kernel::{ exception }; +use super::error::MachineOk; + /// # Exceptions /// /// Textual names of the exceptions that can be generated by user program @@ -224,13 +226,13 @@ impl Machine { s } - pub fn raise_exception(&mut self, exception: ExceptionType, address : u64) -> Result<(), MachineError>{ + pub fn raise_exception(&mut self, exception: ExceptionType, address : u64) -> Result{ self.set_status(MachineStatus::SystemMode); // Handle the interruption exception::call(exception, self); // todo: return error if the syscall code is invalid self.set_status(MachineStatus::UserMode); - Ok(()) + Ok(MachineOk::Ok) } /// Execute the instructions table of a machine putted in param @@ -252,7 +254,7 @@ impl Machine { /// ### Parameters /// /// - **machine** which contains a table of instructions and a pc to the actual instruction - pub fn one_instruction(&mut self) -> Result<(), MachineError> { + pub fn one_instruction(&mut self) -> Result { if self.main_memory.len() <= self.pc as usize { panic!("ERROR : number max of instructions rushed"); @@ -276,20 +278,20 @@ impl Machine { // Treatment for: LOAD UPPER IMMEDIATE INSTRUCTION RISCV_LUI => { self.int_reg.set_reg(inst.rd, inst.imm31_12 as i64); - Ok(()) + Ok(MachineOk::Ok) }, // Treatment for: ADD UPPER IMMEDIATE TO PC INSTRUCTION RISCV_AUIPC => { self.int_reg.set_reg(inst.rd, self.pc as i64 - 4 + inst.imm31_12 as i64); - Ok(()) + Ok(MachineOk::Ok) }, // Treatement for: JUMP AND LINK INSTRUCTIONS (direct jump) RISCV_JAL => { self.int_reg.set_reg(inst.rd, self.pc as i64); self.pc = (self.pc as i64 + inst.imm21_1_signed as i64 - 4) as u64; - Ok(()) + Ok((MachineOk::Ok)) }, // Treatment for: JUMP AND LINK REGISTER INSTRUCTIONS (indirect jump) @@ -297,7 +299,7 @@ impl Machine { let tmp = self.pc; self.pc = (self.int_reg.get_reg(inst.rs1) + inst.imm12_I_signed as i64) as u64 & 0xfffffffe; self.int_reg.set_reg(inst.rd, tmp as i64); - Ok(()) + Ok((MachineOk::Ok)) }, // Treatment for: BRANCH INSTRUCTIONS @@ -333,7 +335,7 @@ impl Machine { } /// Treatement for Branch instructions - fn branch_instruction(&mut self, inst: Instruction) -> Result<(), MachineError> { + fn branch_instruction(&mut self, inst: Instruction) -> Result { let op = match inst.funct3 { RISCV_BR_BEQ => |a, b| a == b, RISCV_BR_BNE => |a, b| a != b, @@ -348,15 +350,15 @@ impl Machine { if op(rs1, rs2) { self.pc = (self.pc as i64 + inst.imm13_signed as i64 - 4) as u64; } - Ok(()) + Ok(MachineOk::Ok) } /// Executes RISC-V Load Instructions on the machine - fn load_instruction(&mut self, inst: Instruction) -> Result<(), MachineError> { + fn load_instruction(&mut self, inst: Instruction) -> Result { let mut set_reg = |rd, size| { let val = self.read_memory(size, (self.int_reg.get_reg(inst.rs1) + inst.imm12_I_signed as i64) as usize) as i64; self.int_reg.set_reg(rd, val); - Ok(()) + Ok(MachineOk::Ok) }; match inst.funct3 { RISCV_LD_LB | RISCV_LD_LBU => set_reg(inst.rd, 1), @@ -368,14 +370,14 @@ impl Machine { } /// Executes RISC-V Store Instructions on the machine - fn store_instruction(&mut self, inst: Instruction) -> Result<(), MachineError> { + fn store_instruction(&mut self, inst: Instruction) -> Result { let mut store = |size| { self.write_memory( size, (self.int_reg.get_reg(inst.rs1) + inst.imm12_S_signed as i64) as usize, self.int_reg.get_reg(inst.rs2) as u64 ); - Ok(()) + Ok(MachineOk::Ok) }; match inst.funct3 { RISCV_ST_STB => store(1), @@ -387,13 +389,13 @@ impl Machine { } /// Executes RISC-V Integer Register-Immediate Instructions on the machine - fn opi_instruction(&mut self, inst: Instruction) -> Result<(), MachineError> { + fn opi_instruction(&mut self, inst: Instruction) -> Result { let rs1 = self.int_reg.get_reg(inst.rs1); let imm12 = inst.imm12_I_signed as i64; let shamt = inst.shamt as i64; let mut compute = |operation: &dyn Fn (i64, i64) -> i64, a, b| { self.int_reg.set_reg(inst.rd, operation(a, b)); - Ok(()) + Ok(MachineOk::Ok) }; match inst.funct3 { RISCV_OPI_ADDI => compute(&std::ops::Add::add, rs1, imm12), @@ -412,7 +414,7 @@ impl Machine { } /// Executes simple RISC-V mathematical operations on the machine - fn op_instruction(&mut self, inst: Instruction) -> Result<(), MachineError> { + fn op_instruction(&mut self, inst: Instruction) -> Result { let long_result: i128; let unsigned_reg1: u64; let unsigned_reg2: u64; @@ -469,11 +471,11 @@ impl Machine { _ => Err(format!("Unreachable in op_instruction match! Instruction was {:?}", inst))? } } - Ok(()) + Ok(MachineOk::Ok) } /// Exectutes simple RISC-V *iw instructions on the machine - fn opiw_instruction(&mut self, inst: Instruction) -> Result<(), MachineError> { + fn opiw_instruction(&mut self, inst: Instruction) -> Result { let local_data = self.int_reg.get_reg(inst.rs1); let result = match inst.funct3 { RISCV_OPIW_ADDIW => local_data + inst.imm12_I_signed as i64, @@ -482,11 +484,11 @@ impl Machine { _ => Err(format!("Unreachable in op_instruction match! Instruction was {:?}", inst))? }; self.int_reg.set_reg(inst.rd, result); - Ok(()) + Ok(MachineOk::Ok) } /// Executes simple RISC-V *w instructions on the machine - fn opw_instruction(&mut self, inst: Instruction) -> Result<(), MachineError> { + fn opw_instruction(&mut self, inst: Instruction) -> Result { if inst.funct7 == 1 { // rv64m let local_data_a = self.int_reg.get_reg(inst.rs1) & 0xffffffff; let local_data_b = self.int_reg.get_reg(inst.rs2) & 0xffffffff; @@ -521,25 +523,25 @@ impl Machine { _ => Err(format!("Unreachable in opw_instruction match! Instruction was {:?}", inst))? } } - Ok(()) + Ok(MachineOk::Ok) } /// Executes simple RISC-V floating point instructions on the machine. /// /// See Risc-V Spec v2.2 Chapter 8: “F” Standard Extension for Single-Precision Floating-Point, Version 2.0. - fn fp_instruction(&mut self, inst: Instruction) -> Result<(), MachineError> { + fn fp_instruction(&mut self, inst: Instruction) -> Result { let mut set_reg = |operation: &dyn Fn (f32, f32) -> f32| { let a = self.fp_reg.get_reg(inst.rs1); let b = self.fp_reg.get_reg(inst.rs2); self.fp_reg.set_reg(inst.rd, operation(a, b)); - Ok(()) + Ok(MachineOk::Ok) }; match inst.funct7 { RISCV_FP_ADD => set_reg(&core::ops::Add::add), RISCV_FP_SUB => set_reg(&core::ops::Sub::sub), RISCV_FP_MUL => set_reg(&core::ops::Mul::mul), RISCV_FP_DIV => set_reg(&core::ops::Div::div), - RISCV_FP_SQRT => { self.fp_reg.set_reg(inst.rd, self.fp_reg.get_reg(inst.rs1).sqrt()); Ok(()) }, + RISCV_FP_SQRT => { self.fp_reg.set_reg(inst.rd, self.fp_reg.get_reg(inst.rs1).sqrt()); Ok(MachineOk::Ok) }, RISCV_FP_FSGN => self.fp_fsgn_instruction(inst), RISCV_FP_MINMAX => self.fp_minmax_instruction(inst), RISCV_FP_FCVTW => self.fp_fcvtw_instruction(inst), @@ -552,7 +554,7 @@ impl Machine { } /// Executes RISC-V sign-injection instruction on floating point values on the machine. - fn fp_fsgn_instruction(&mut self, inst: Instruction) -> Result<(), MachineError> { + fn fp_fsgn_instruction(&mut self, inst: Instruction) -> Result { let local_float = self.fp_reg.get_reg(inst.rs1); match inst.funct3 { RISCV_FP_FSGN_J => if self.fp_reg.get_reg(inst.rs2) < 0f32 { @@ -573,11 +575,11 @@ impl Machine { }, _ => Err(format!("Unreachable in fp_fsgn_instruction! Instruction was {:?}", inst))? } - Ok(()) + Ok(MachineOk::Ok) } /// Executes RISC-V min / max instruction on floating point values on the machine. - fn fp_minmax_instruction(&mut self, inst: Instruction) -> Result<(), MachineError> { + fn fp_minmax_instruction(&mut self, inst: Instruction) -> Result { let r1 = self.fp_reg.get_reg(inst.rs1); let r2 = self.fp_reg.get_reg(inst.rs2); match inst.funct3 { @@ -585,54 +587,54 @@ impl Machine { RISCV_FP_MINMAX_MAX => self.fp_reg.set_reg(inst.rd, if r1 > r2 {r1} else {r2}), _ => Err(format!("Unreachable in fp_minmax_instruction! Instruction was {:?}", inst))? }; - Ok(()) + Ok(MachineOk::Ok) } /// Executes RISC-V floating-point to integer conversion instruction on the machine. - fn fp_fcvtw_instruction(&mut self, inst: Instruction) -> Result<(), MachineError> { + fn fp_fcvtw_instruction(&mut self, inst: Instruction) -> Result { if inst.rs2 == RISCV_FP_FCVTW_W { self.int_reg.set_reg(inst.rd, self.fp_reg.get_reg(inst.rs1) as i64) } else { self.int_reg.set_reg(inst.rd, (self.fp_reg.get_reg(inst.rs1) as u64) as i64) } - Ok(()) + Ok(MachineOk::Ok) } /// Executes RISC-V integer to floating-point conversion instruction on the machine. - fn fp_fcvts_instruction(&mut self, inst: Instruction) -> Result<(), MachineError> { + fn fp_fcvts_instruction(&mut self, inst: Instruction) -> Result { if inst.rs2 == RISCV_FP_FCVTS_W { self.fp_reg.set_reg(inst.rd, self.int_reg.get_reg(inst.rs1) as f32); } else { self.fp_reg.set_reg(inst.rd, (self.int_reg.get_reg(inst.rs1) as u32) as f32); } - Ok(()) + Ok(MachineOk::Ok) } /// Executes RISC-V move from int_reg to fp_reg instruction on the machine. - fn fp_fmvw_instruction(&mut self, inst: Instruction) -> Result<(), MachineError> { + fn fp_fmvw_instruction(&mut self, inst: Instruction) -> Result { self.fp_reg.set_reg(inst.rd, self.int_reg.get_reg(inst.rs1) as f32); - Ok(()) + Ok(MachineOk::Ok) } /// Executes RISC-V move from fp_reg to int_reg instruction on the machine. - fn fp_fmvxfclass_instruction(&mut self, inst: Instruction) -> Result<(), MachineError> { + fn fp_fmvxfclass_instruction(&mut self, inst: Instruction) -> Result { if inst.funct3 == RISCV_FP_FMVXFCLASS_FMVX { self.int_reg.set_reg(inst.rd, self.fp_reg.get_reg(inst.rs1) as i64); - Ok(()) + Ok(MachineOk::Ok) } else { Err(format!("Unreachable in fp_fmvxfclass_instruction! Instruction was {:?}", inst))? } } /// Executes RISC-V floating point values comparaison instructions on the machine. - fn fp_fcmp_instruction(&mut self, inst: Instruction) -> Result<(), MachineError> { + fn fp_fcmp_instruction(&mut self, inst: Instruction) -> Result { match inst.funct3 { RISCV_FP_FCMP_FEQ => self.int_reg.set_reg(inst.rd, (self.fp_reg.get_reg(inst.rs1) == self.fp_reg.get_reg(inst.rs2)) as i64), RISCV_FP_FCMP_FLT => self.int_reg.set_reg(inst.rd, (self.fp_reg.get_reg(inst.rs1) < self.fp_reg.get_reg(inst.rs2)) as i64), RISCV_FP_FCMP_FLE => self.int_reg.set_reg(inst.rd, (self.fp_reg.get_reg(inst.rs1) <= self.fp_reg.get_reg(inst.rs2)) as i64), _ => Err(format!("Unreachable in fp_fcmp_instruction match! Instruction was {:?}", inst))? } - Ok(()) + Ok(MachineOk::Ok) } /// print memory FOR DEBUG