From 72f560f3ecf0d70d59d214080f7359e49e9d5f63 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fran=C3=A7ois=20Autin?= Date: Wed, 29 Mar 2023 15:25:58 +0200 Subject: [PATCH] :recycle: Simplified fp_instruction --- src/simulator/machine.rs | 361 +++++++++++++++++++++------------------ 1 file changed, 199 insertions(+), 162 deletions(-) diff --git a/src/simulator/machine.rs b/src/simulator/machine.rs index 55a31e5..a798dd5 100644 --- a/src/simulator/machine.rs +++ b/src/simulator/machine.rs @@ -275,28 +275,28 @@ impl Machine { }, // Treatment for: BRANCH INSTRUCTIONS - RISCV_BR => self.branch_instruction(inst), + RISCV_BR => self.branch_instruction(inst), // Treatment for: LOAD INSTRUCTIONS - RISCV_LD => self.load_instruction(inst), + RISCV_LD => self.load_instruction(inst), // Treatment for: STORE INSTRUCTIONS - RISCV_ST => self.store_instruction(inst), - - // Treatment for: OPI INSTRUCTIONS - RISCV_OPI => self.opi_instruction(inst), + RISCV_ST => self.store_instruction(inst), // Treatment for: OP INSTRUCTIONS - RISCV_OP => self.op_instruction(inst), + RISCV_OP => self.op_instruction(inst), + + // Treatment for: OPI INSTRUCTIONS + RISCV_OPI => self.opi_instruction(inst), + + // Treatment for: OPW INSTRUCTIONS + RISCV_OPW => self.opw_instruction(inst), // Treatment for OPIW INSTRUCTIONS - RISCV_OPIW => self.opiw_instruction(inst), - - // Treatment for: OPW INSTRUCTIONS - RISCV_OPW => self.opw_instruction(inst), + RISCV_OPIW => self.opiw_instruction(inst), // Treatment for: FLOATING POINT INSTRUCTIONS - RISCV_FP => self.fp_instruction(inst), + RISCV_FP => self.fp_instruction(inst), // Treatment for: SYSTEM CALLS RISCV_SYSTEM => Err(format!("{:x}: System opcode\npc: {:x}", inst.opcode, self.pc))?, @@ -315,7 +315,7 @@ impl Machine { RISCV_BR_BGE => |a, b| a >= b, RISCV_BR_BLTU => |a, b| a < b, RISCV_BR_BGEU => |a, b| a >= b, - _ => unreachable!() + _ => Err(format!("Unreachable in branch_instruction match! Instruction was {:?}", inst))? }; let rs1 = self.int_reg.get_reg(inst.rs1); let rs2 = self.int_reg.get_reg(inst.rs2); @@ -333,11 +333,11 @@ impl Machine { Ok(()) }; match inst.funct3 { - RISCV_LD_LB | RISCV_LD_LBU => set_reg(inst.rd, 1), - RISCV_LD_LH | RISCV_LD_LHU => set_reg(inst.rd, 2), - RISCV_LD_LW | RISCV_LD_LWU => set_reg(inst.rd, 4), - RISCV_LD_LD => set_reg(inst.rd, 8), - _ => Err(format!("In LD switch case, this should never happen... Instr was {}", inst.value).as_str())? + RISCV_LD_LB | RISCV_LD_LBU => set_reg(inst.rd, 1), + RISCV_LD_LH | RISCV_LD_LHU => set_reg(inst.rd, 2), + RISCV_LD_LW | RISCV_LD_LWU => set_reg(inst.rd, 4), + RISCV_LD_LD => set_reg(inst.rd, 8), + _ => Err(format!("Unreachable in load_instruction match! Instruction was {:?}", inst))? } } @@ -356,7 +356,7 @@ impl Machine { RISCV_ST_STH => store(2), RISCV_ST_STW => store(4), RISCV_ST_STD => store(8), - _ => Err(format!("In ST switch case, this should never happen... Instr was {}", inst.value).as_str())? + _ => Err(format!("Unreachable in store_instruction match! Instruction was {:?}", inst))? } } @@ -370,18 +370,18 @@ impl Machine { Ok(()) }; match inst.funct3 { - RISCV_OPI_ADDI => compute(&std::ops::Add::add, rs1, imm12), - RISCV_OPI_SLTI => compute(&|a, b| (a < b) as i64, rs1, imm12), - RISCV_OPI_XORI => compute(&core::ops::BitXor::bitxor, rs1, imm12), - RISCV_OPI_ORI => compute(&core::ops::BitOr::bitor, rs1, imm12), - RISCV_OPI_ANDI => compute(&core::ops::BitAnd::bitand, rs1, imm12), - RISCV_OPI_SLLI => compute(&core::ops::Shl::shl, rs1, imm12), - RISCV_OPI_SRI => if inst.funct7_smaller == RISCV_OPI_SRI_SRLI { - compute(&|a, b| { (a >> b) & self.shiftmask[inst.shamt as usize] as i64 }, rs1, shamt) - } else { - compute(&core::ops::Shr::shr, rs1, shamt) - } - _ => Err(format!("In OPI switch case, this should never happen... Instr was %x\n {}", inst.value))? + RISCV_OPI_ADDI => compute(&std::ops::Add::add, rs1, imm12), + RISCV_OPI_SLTI => compute(&|a, b| (a < b) as i64, rs1, imm12), + RISCV_OPI_XORI => compute(&core::ops::BitXor::bitxor, rs1, imm12), + RISCV_OPI_ORI => compute(&core::ops::BitOr::bitor, rs1, imm12), + RISCV_OPI_ANDI => compute(&core::ops::BitAnd::bitand, rs1, imm12), + RISCV_OPI_SLLI => compute(&core::ops::Shl::shl, rs1, imm12), + RISCV_OPI_SRI => if inst.funct7_smaller == RISCV_OPI_SRI_SRLI { + compute(&|a, b| { (a >> b) & self.shiftmask[inst.shamt as usize] as i64 }, rs1, shamt) + } else { + compute(&core::ops::Shr::shr, rs1, shamt) + } + _ => Err(format!("Unreachable in opi_instruction match! Instruction was {:?}", inst))? } } @@ -392,55 +392,55 @@ impl Machine { let unsigned_reg2: u64; if inst.funct7 == 1 { match inst.funct3 { - RISCV_OP_M_MUL => { - long_result = (self.int_reg.get_reg(inst.rs1) * self.int_reg.get_reg(inst.rs2)) as i128; - self.int_reg.set_reg(inst.rd, (long_result & 0xffffffffffffffff) as i64) - }, - RISCV_OP_M_MULH => { - long_result = (self.int_reg.get_reg(inst.rs1) * self.int_reg.get_reg(inst.rs2)) as i128; - self.int_reg.set_reg(inst.rd, ((long_result >> 64) & 0xffffffffffffffff) as i64) - }, - RISCV_OP_M_MULHSU => { - unsigned_reg2 = self.int_reg.get_reg(inst.rs2) as u64; - long_result = (self.int_reg.get_reg(inst.rs1) as u64 * unsigned_reg2) as i128; - self.int_reg.set_reg(inst.rd, ((long_result >> 64) & 0xffffffffffffffff) as i64) - }, - RISCV_OP_M_MULHU => { - unsigned_reg1 = self.int_reg.get_reg(inst.rs1) as u64; - unsigned_reg2 = self.int_reg.get_reg(inst.rs2) as u64; - long_result = (unsigned_reg1 * unsigned_reg2) as i128; - self.int_reg.set_reg(inst.rd, ((long_result >> 64) & 0xffffffffffffffff) as i64); - }, - RISCV_OP_M_DIV => self.int_reg.set_reg(inst.rd, self.int_reg.get_reg(inst.rs1) / self.int_reg.get_reg(inst.rs2)), - _ => panic!("RISCV_OP : funct7 = 1 (Multiplication) :: Error\n") + RISCV_OP_M_MUL => { + long_result = (self.int_reg.get_reg(inst.rs1) * self.int_reg.get_reg(inst.rs2)) as i128; + self.int_reg.set_reg(inst.rd, (long_result & 0xffffffffffffffff) as i64) + }, + RISCV_OP_M_MULH => { + long_result = (self.int_reg.get_reg(inst.rs1) * self.int_reg.get_reg(inst.rs2)) as i128; + self.int_reg.set_reg(inst.rd, ((long_result >> 64) & 0xffffffffffffffff) as i64) + }, + RISCV_OP_M_MULHSU => { + unsigned_reg2 = self.int_reg.get_reg(inst.rs2) as u64; + long_result = (self.int_reg.get_reg(inst.rs1) as u64 * unsigned_reg2) as i128; + self.int_reg.set_reg(inst.rd, ((long_result >> 64) & 0xffffffffffffffff) as i64) + }, + RISCV_OP_M_MULHU => { + unsigned_reg1 = self.int_reg.get_reg(inst.rs1) as u64; + unsigned_reg2 = self.int_reg.get_reg(inst.rs2) as u64; + long_result = (unsigned_reg1 * unsigned_reg2) as i128; + self.int_reg.set_reg(inst.rd, ((long_result >> 64) & 0xffffffffffffffff) as i64); + }, + RISCV_OP_M_DIV => self.int_reg.set_reg(inst.rd, self.int_reg.get_reg(inst.rs1) / self.int_reg.get_reg(inst.rs2)), + _ => Err(format!("Unreachable in op_instruction match! Instruction was {:?}", inst))? } } else { match inst.funct3 { - RISCV_OP_ADD => if inst.funct7 == RISCV_OP_ADD_ADD { - self.int_reg.set_reg(inst.rd, self.int_reg.get_reg(inst.rs1) + self.int_reg.get_reg(inst.rs2)) - } else { - self.int_reg.set_reg(inst.rd, self.int_reg.get_reg(inst.rs1) - self.int_reg.get_reg(inst.rs2)) - }, - RISCV_OP_SLL => self.int_reg.set_reg(inst.rd, self.int_reg.get_reg(inst.rs1) << (self.int_reg.get_reg(inst.rs2) & 0x3f)), - RISCV_OP_SLT => if self.int_reg.get_reg(inst.rs1) < self.int_reg.get_reg(inst.rs2) { - self.int_reg.set_reg(inst.rd, 1) - } else { - self.int_reg.set_reg(inst.rd, 0) - }, - RISCV_OP_SLTU => { - unsigned_reg1 = self.int_reg.get_reg(inst.rs1) as u64; - unsigned_reg2 = self.int_reg.get_reg(inst.rs2) as u64; - if unsigned_reg1 < unsigned_reg2 { - self.int_reg.set_reg(inst.rd, 1) - } else { - self.int_reg.set_reg(inst.rd, 0) - } - }, - RISCV_OP_XOR => self.int_reg.set_reg(inst.rd, self.int_reg.get_reg(inst.rs1) ^ self.int_reg.get_reg(inst.rs2)), - RISCV_OP_SR => self.int_reg.set_reg(inst.rd, self.int_reg.get_reg(inst.rs1) >> self.int_reg.get_reg(inst.rs2)), // RISCV_OP_SR_SRL inaccessible - RISCV_OP_OR => self.int_reg.set_reg(inst.rd, self.int_reg.get_reg(inst.rs1) | self.int_reg.get_reg(inst.rs2)), - RISCV_OP_AND => self.int_reg.set_reg(inst.rd, self.int_reg.get_reg(inst.rs1) & self.int_reg.get_reg(inst.rs2)), - _ => panic!("RISCV_OP undefined case\n") + RISCV_OP_ADD => if inst.funct7 == RISCV_OP_ADD_ADD { + self.int_reg.set_reg(inst.rd, self.int_reg.get_reg(inst.rs1) + self.int_reg.get_reg(inst.rs2)) + } else { + self.int_reg.set_reg(inst.rd, self.int_reg.get_reg(inst.rs1) - self.int_reg.get_reg(inst.rs2)) + }, + RISCV_OP_SLL => self.int_reg.set_reg(inst.rd, self.int_reg.get_reg(inst.rs1) << (self.int_reg.get_reg(inst.rs2) & 0x3f)), + RISCV_OP_SLT => if self.int_reg.get_reg(inst.rs1) < self.int_reg.get_reg(inst.rs2) { + self.int_reg.set_reg(inst.rd, 1) + } else { + self.int_reg.set_reg(inst.rd, 0) + }, + RISCV_OP_SLTU => { + unsigned_reg1 = self.int_reg.get_reg(inst.rs1) as u64; + unsigned_reg2 = self.int_reg.get_reg(inst.rs2) as u64; + if unsigned_reg1 < unsigned_reg2 { + self.int_reg.set_reg(inst.rd, 1) + } else { + self.int_reg.set_reg(inst.rd, 0) + } + }, + RISCV_OP_XOR => self.int_reg.set_reg(inst.rd, self.int_reg.get_reg(inst.rs1) ^ self.int_reg.get_reg(inst.rs2)), + RISCV_OP_SR => self.int_reg.set_reg(inst.rd, self.int_reg.get_reg(inst.rs1) >> self.int_reg.get_reg(inst.rs2)), // RISCV_OP_SR_SRL inaccessible + RISCV_OP_OR => self.int_reg.set_reg(inst.rd, self.int_reg.get_reg(inst.rs1) | self.int_reg.get_reg(inst.rs2)), + RISCV_OP_AND => self.int_reg.set_reg(inst.rd, self.int_reg.get_reg(inst.rs1) & self.int_reg.get_reg(inst.rs2)), + _ => Err(format!("Unreachable in op_instruction match! Instruction was {:?}", inst))? } } Ok(()) @@ -452,8 +452,8 @@ impl Machine { let result = match inst.funct3 { RISCV_OPIW_ADDIW => local_data + inst.imm12_I_signed as i64, RISCV_OPIW_SLLIW => local_data << inst.shamt, - RISCV_OPIW_SRW => (local_data >> inst.shamt) & if inst.funct7 == RISCV_OPIW_SRW_SRLIW { self.shiftmask[32 + inst.shamt as usize] as i64 } else { 1 }, - _ => Err("In OPI switch case, this should never happen... Instr was {}\n")?, + RISCV_OPIW_SRW => (local_data >> inst.shamt) & if inst.funct7 == RISCV_OPIW_SRW_SRLIW { self.shiftmask[32 + inst.shamt as usize] as i64 } else { 1 }, + _ => Err(format!("Unreachable in op_instruction match! Instruction was {:?}", inst))? }; self.int_reg.set_reg(inst.rd, result); Ok(()) @@ -469,105 +469,142 @@ impl Machine { // Match case for multiplication operations (in standard extension RV32M) match inst.funct3 { - RISCV_OPW_M_MULW => self.int_reg.set_reg(inst.rd, local_data_a * local_data_b), - RISCV_OPW_M_DIVW => self.int_reg.set_reg(inst.rd, local_data_a / local_data_b), - RISCV_OPW_M_DIVUW => self.int_reg.set_reg(inst.rd, local_data_a_unsigned / local_data_b_unsigned), - RISCV_OPW_M_REMW => self.int_reg.set_reg(inst.rd, local_data_a % local_data_b), - RISCV_OPW_M_REMUW => self.int_reg.set_reg(inst.rd, local_data_a_unsigned % local_data_b_unsigned), - _ => panic!("this instruction ({}) doesn't exists", inst.value) + RISCV_OPW_M_MULW => self.int_reg.set_reg(inst.rd, local_data_a * local_data_b), + RISCV_OPW_M_DIVW => self.int_reg.set_reg(inst.rd, local_data_a / local_data_b), + RISCV_OPW_M_DIVUW => self.int_reg.set_reg(inst.rd, local_data_a_unsigned / local_data_b_unsigned), + RISCV_OPW_M_REMW => self.int_reg.set_reg(inst.rd, local_data_a % local_data_b), + RISCV_OPW_M_REMUW => self.int_reg.set_reg(inst.rd, local_data_a_unsigned % local_data_b_unsigned), + _ => Err(format!("Unreachable in opw_instruction match! Instruction was {:?}", inst))? } } else { // others rv64 OPW operations let local_dataa = self.int_reg.get_reg(inst.rs1) & 0xffffffff; let local_datab = self.int_reg.get_reg(inst.rs2) & 0xffffffff; // Match case for base OP operation match inst.funct3 { - RISCV_OPW_ADDSUBW => if inst.funct7 == RISCV_OPW_ADDSUBW_ADDW { - self.int_reg.set_reg(inst.rd, local_dataa + local_datab); - } else { // SUBW - self.int_reg.set_reg(inst.rd, local_dataa - local_datab); - }, - RISCV_OPW_SLLW => self.int_reg.set_reg(inst.rd, local_dataa << (local_datab & 0x1f)), - RISCV_OPW_SRW => if inst.funct7 == RISCV_OPW_SRW_SRLW { - self.int_reg.set_reg(inst.rd, local_dataa >> (local_datab & 0x1f) & self.shiftmask[32 + local_datab as usize] as i64) - } else { // SRAW - self.int_reg.set_reg(inst.rd, local_dataa >> (local_datab & 0x1f)) - }, - _ => panic!("this instruction ({}) doesn't exist", inst.value) + RISCV_OPW_ADDSUBW => if inst.funct7 == RISCV_OPW_ADDSUBW_ADDW { + self.int_reg.set_reg(inst.rd, local_dataa + local_datab); + } else { // SUBW + self.int_reg.set_reg(inst.rd, local_dataa - local_datab); + }, + RISCV_OPW_SLLW => self.int_reg.set_reg(inst.rd, local_dataa << (local_datab & 0x1f)), + RISCV_OPW_SRW => if inst.funct7 == RISCV_OPW_SRW_SRLW { + self.int_reg.set_reg(inst.rd, local_dataa >> (local_datab & 0x1f) & self.shiftmask[32 + local_datab as usize] as i64) + } else { // SRAW + self.int_reg.set_reg(inst.rd, local_dataa >> (local_datab & 0x1f)) + }, + _ => Err(format!("Unreachable in opw_instruction match! Instruction was {:?}", inst))? } } Ok(()) } - /// Executes simple RISC-V floating point instructions on the machine + /// 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> { + 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(()) + }; match inst.funct7 { - RISCV_FP_ADD => self.fp_reg.set_reg(inst.rd, self.fp_reg.get_reg(inst.rs1) + self.fp_reg.get_reg(inst.rs2)), - RISCV_FP_SUB => self.fp_reg.set_reg(inst.rd, self.fp_reg.get_reg(inst.rs1) - self.fp_reg.get_reg(inst.rs2)), - RISCV_FP_MUL => self.fp_reg.set_reg(inst.rd, self.fp_reg.get_reg(inst.rs1) * self.fp_reg.get_reg(inst.rs2)), - RISCV_FP_DIV => self.fp_reg.set_reg(inst.rd, self.fp_reg.get_reg(inst.rs1) / self.fp_reg.get_reg(inst.rs2)), - RISCV_FP_SQRT => self.fp_reg.set_reg(inst.rd, self.fp_reg.get_reg(inst.rs1).sqrt()), - RISCV_FP_FSGN => { - 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 { - self.fp_reg.set_reg(inst.rd, -local_float) - } else { - self.fp_reg.set_reg(inst.rd, local_float) - }, - RISCV_FP_FSGN_JN => if self.fp_reg.get_reg(inst.rs2) < 0f32 { - self.fp_reg.set_reg(inst.rd, local_float) - } else { - self.fp_reg.set_reg(inst.rd, -local_float) - }, - RISCV_FP_FSGN_JX => if (self.fp_reg.get_reg(inst.rs2) < 0.0 && self.fp_reg.get_reg(inst.rs1) >= 0.0) || - (self.fp_reg.get_reg(inst.rs2) >= 0.0 && self.fp_reg.get_reg(inst.rs1) < 0.0) { - self.fp_reg.set_reg(inst.rd, -local_float) - } else { - self.fp_reg.set_reg(inst.rd, local_float) - }, - _ => panic!("this instruction ({}) doesn't exists", inst.value) - } + 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_FSGN => self.fp_fsgn_instruction(inst), + RISCV_FP_MINMAX => self.fp_minmax_instruction(inst), + RISCV_FP_FCVTW => self.fp_fcvtw_instruction(inst), + RISCV_FP_FCVTS => self.fp_fcvts_instruction(inst), + RISCV_FP_FMVW => self.fp_fmvw_instruction(inst), + RISCV_FP_FMVXFCLASS => self.fp_fmvxfclass_instruction(inst), + RISCV_FP_FCMP => self.fp_fcmp_instruction(inst), + _ => Err(format!("Unreachable in fp_instruction match! Instruction was {:?}", inst))? + } + } + + /// Executes RISC-V sign-injection instruction on floating point values on the machine. + fn fp_fsgn_instruction(&mut self, inst: Instruction) -> Result<(), 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 { + self.fp_reg.set_reg(inst.rd, -local_float); + } else { + self.fp_reg.set_reg(inst.rd, local_float); }, - RISCV_FP_MINMAX => { - let r1 = self.fp_reg.get_reg(inst.rs1); - let r2 = self.fp_reg.get_reg(inst.rs2); - match inst.funct3 { - RISCV_FP_MINMAX_MIN => self.fp_reg.set_reg(inst.rd, if r1 < r2 {r1} else {r2}), - RISCV_FP_MINMAX_MAX => self.fp_reg.set_reg(inst.rd, if r1 > r2 {r1} else {r2}), - _ => panic!("this instruction ({}) doesn't exists", inst.value) - } + RISCV_FP_FSGN_JN => if self.fp_reg.get_reg(inst.rs2) < 0f32 { + self.fp_reg.set_reg(inst.rd, local_float); + } else { + self.fp_reg.set_reg(inst.rd, -local_float); }, - RISCV_FP_FCVTW => { - 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) - } + RISCV_FP_FSGN_JX => if (self.fp_reg.get_reg(inst.rs2) < 0.0 && self.fp_reg.get_reg(inst.rs1) >= 0.0) || + (self.fp_reg.get_reg(inst.rs2) >= 0.0 && self.fp_reg.get_reg(inst.rs1) < 0.0) { + self.fp_reg.set_reg(inst.rd, -local_float); + } else { + self.fp_reg.set_reg(inst.rd, local_float); }, - RISCV_FP_FCVTS => { - 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); - } - }, - RISCV_FP_FMVW => self.fp_reg.set_reg(inst.rd, self.int_reg.get_reg(inst.rs1) as f32), - RISCV_FP_FMVXFCLASS => { - if inst.funct3 == RISCV_FP_FMVXFCLASS_FMVX { - self.int_reg.set_reg(inst.rd, self.fp_reg.get_reg(inst.rs1) as i64); - } else { - panic!("Fclass instruction is not handled in riscv simulator"); - } - }, - RISCV_FP_FCMP => { - 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), - _ => panic!("this instruction ({}) doesn't exists", inst.value) - } - }, - _ => panic!("this instruction ({}) doesn't exists", inst.value) + _ => Err(format!("Unreachable in fp_fsgn_instruction! Instruction was {:?}", inst))? + } + Ok(()) + } + + /// Executes RISC-V min / max instruction on floating point values on the machine. + fn fp_minmax_instruction(&mut self, inst: Instruction) -> Result<(), MachineError> { + let r1 = self.fp_reg.get_reg(inst.rs1); + let r2 = self.fp_reg.get_reg(inst.rs2); + match inst.funct3 { + RISCV_FP_MINMAX_MIN => self.fp_reg.set_reg(inst.rd, if r1 < r2 {r1} else {r2}), + 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(()) + } + + /// Executes RISC-V floating-point to integer conversion instruction on the machine. + fn fp_fcvtw_instruction(&mut self, inst: Instruction) -> Result<(), 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(()) + } + + /// Executes RISC-V integer to floating-point conversion instruction on the machine. + fn fp_fcvts_instruction(&mut self, inst: Instruction) -> Result<(), 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(()) + } + + /// Executes RISC-V move from int_reg to fp_reg instruction on the machine. + fn fp_fmvw_instruction(&mut self, inst: Instruction) -> Result<(), MachineError> { + self.fp_reg.set_reg(inst.rd, self.int_reg.get_reg(inst.rs1) as f32); + 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> { + if inst.funct3 == RISCV_FP_FMVXFCLASS_FMVX { + self.int_reg.set_reg(inst.rd, self.fp_reg.get_reg(inst.rs1) as i64); + 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> { + 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(()) }