Added MachineOk to one_instruction

This commit is contained in:
Samy Solhi 2023-03-29 17:01:28 +02:00
parent ac1f2287a2
commit 06f6137852
2 changed files with 45 additions and 38 deletions

View File

@ -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.
///
/// ```

View File

@ -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<MachineOk, MachineError>{
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<MachineOk, MachineError> {
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<MachineOk, MachineError> {
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<MachineOk, MachineError> {
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<MachineOk, MachineError> {
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<MachineOk, MachineError> {
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<MachineOk, MachineError> {
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<MachineOk, MachineError> {
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<MachineOk, MachineError> {
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<MachineOk, MachineError> {
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<MachineOk, MachineError> {
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<MachineOk, MachineError> {
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<MachineOk, MachineError> {
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<MachineOk, MachineError> {
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<MachineOk, MachineError> {
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<MachineOk, MachineError> {
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<MachineOk, MachineError> {
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