♻️ Simplified fp_instruction
This commit is contained in:
parent
2e41758a52
commit
72f560f3ec
@ -283,18 +283,18 @@ impl Machine {
|
|||||||
// Treatment for: STORE INSTRUCTIONS
|
// Treatment for: STORE INSTRUCTIONS
|
||||||
RISCV_ST => self.store_instruction(inst),
|
RISCV_ST => self.store_instruction(inst),
|
||||||
|
|
||||||
// Treatment for: OPI INSTRUCTIONS
|
|
||||||
RISCV_OPI => self.opi_instruction(inst),
|
|
||||||
|
|
||||||
// Treatment for: OP INSTRUCTIONS
|
// Treatment for: OP INSTRUCTIONS
|
||||||
RISCV_OP => self.op_instruction(inst),
|
RISCV_OP => self.op_instruction(inst),
|
||||||
|
|
||||||
// Treatment for OPIW INSTRUCTIONS
|
// Treatment for: OPI INSTRUCTIONS
|
||||||
RISCV_OPIW => self.opiw_instruction(inst),
|
RISCV_OPI => self.opi_instruction(inst),
|
||||||
|
|
||||||
// Treatment for: OPW INSTRUCTIONS
|
// Treatment for: OPW INSTRUCTIONS
|
||||||
RISCV_OPW => self.opw_instruction(inst),
|
RISCV_OPW => self.opw_instruction(inst),
|
||||||
|
|
||||||
|
// Treatment for OPIW INSTRUCTIONS
|
||||||
|
RISCV_OPIW => self.opiw_instruction(inst),
|
||||||
|
|
||||||
// Treatment for: FLOATING POINT INSTRUCTIONS
|
// Treatment for: FLOATING POINT INSTRUCTIONS
|
||||||
RISCV_FP => self.fp_instruction(inst),
|
RISCV_FP => self.fp_instruction(inst),
|
||||||
|
|
||||||
@ -315,7 +315,7 @@ impl Machine {
|
|||||||
RISCV_BR_BGE => |a, b| a >= b,
|
RISCV_BR_BGE => |a, b| a >= b,
|
||||||
RISCV_BR_BLTU => |a, b| a < b,
|
RISCV_BR_BLTU => |a, b| a < b,
|
||||||
RISCV_BR_BGEU => |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 rs1 = self.int_reg.get_reg(inst.rs1);
|
||||||
let rs2 = self.int_reg.get_reg(inst.rs2);
|
let rs2 = self.int_reg.get_reg(inst.rs2);
|
||||||
@ -337,7 +337,7 @@ impl Machine {
|
|||||||
RISCV_LD_LH | RISCV_LD_LHU => set_reg(inst.rd, 2),
|
RISCV_LD_LH | RISCV_LD_LHU => set_reg(inst.rd, 2),
|
||||||
RISCV_LD_LW | RISCV_LD_LWU => set_reg(inst.rd, 4),
|
RISCV_LD_LW | RISCV_LD_LWU => set_reg(inst.rd, 4),
|
||||||
RISCV_LD_LD => set_reg(inst.rd, 8),
|
RISCV_LD_LD => set_reg(inst.rd, 8),
|
||||||
_ => Err(format!("In LD switch case, this should never happen... Instr was {}", inst.value).as_str())?
|
_ => Err(format!("Unreachable in load_instruction match! Instruction was {:?}", inst))?
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -356,7 +356,7 @@ impl Machine {
|
|||||||
RISCV_ST_STH => store(2),
|
RISCV_ST_STH => store(2),
|
||||||
RISCV_ST_STW => store(4),
|
RISCV_ST_STW => store(4),
|
||||||
RISCV_ST_STD => store(8),
|
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))?
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -381,7 +381,7 @@ impl Machine {
|
|||||||
} else {
|
} else {
|
||||||
compute(&core::ops::Shr::shr, rs1, shamt)
|
compute(&core::ops::Shr::shr, rs1, shamt)
|
||||||
}
|
}
|
||||||
_ => Err(format!("In OPI switch case, this should never happen... Instr was %x\n {}", inst.value))?
|
_ => Err(format!("Unreachable in opi_instruction match! Instruction was {:?}", inst))?
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -412,7 +412,7 @@ impl Machine {
|
|||||||
self.int_reg.set_reg(inst.rd, ((long_result >> 64) & 0xffffffffffffffff) as i64);
|
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)),
|
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")
|
_ => Err(format!("Unreachable in op_instruction match! Instruction was {:?}", inst))?
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
match inst.funct3 {
|
match inst.funct3 {
|
||||||
@ -440,7 +440,7 @@ impl Machine {
|
|||||||
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_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_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)),
|
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")
|
_ => Err(format!("Unreachable in op_instruction match! Instruction was {:?}", inst))?
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Ok(())
|
Ok(())
|
||||||
@ -453,7 +453,7 @@ impl Machine {
|
|||||||
RISCV_OPIW_ADDIW => local_data + inst.imm12_I_signed as i64,
|
RISCV_OPIW_ADDIW => local_data + inst.imm12_I_signed as i64,
|
||||||
RISCV_OPIW_SLLIW => local_data << inst.shamt,
|
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 },
|
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")?,
|
_ => Err(format!("Unreachable in op_instruction match! Instruction was {:?}", inst))?
|
||||||
};
|
};
|
||||||
self.int_reg.set_reg(inst.rd, result);
|
self.int_reg.set_reg(inst.rd, result);
|
||||||
Ok(())
|
Ok(())
|
||||||
@ -474,7 +474,7 @@ impl Machine {
|
|||||||
RISCV_OPW_M_DIVUW => self.int_reg.set_reg(inst.rd, local_data_a_unsigned / local_data_b_unsigned),
|
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_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),
|
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)
|
_ => Err(format!("Unreachable in opw_instruction match! Instruction was {:?}", inst))?
|
||||||
}
|
}
|
||||||
} else { // others rv64 OPW operations
|
} else { // others rv64 OPW operations
|
||||||
let local_dataa = self.int_reg.get_reg(inst.rs1) & 0xffffffff;
|
let local_dataa = self.int_reg.get_reg(inst.rs1) & 0xffffffff;
|
||||||
@ -492,82 +492,119 @@ impl Machine {
|
|||||||
} else { // SRAW
|
} else { // SRAW
|
||||||
self.int_reg.set_reg(inst.rd, local_dataa >> (local_datab & 0x1f))
|
self.int_reg.set_reg(inst.rd, local_dataa >> (local_datab & 0x1f))
|
||||||
},
|
},
|
||||||
_ => panic!("this instruction ({}) doesn't exist", inst.value)
|
_ => Err(format!("Unreachable in opw_instruction match! Instruction was {:?}", inst))?
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Ok(())
|
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> {
|
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 {
|
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_ADD => set_reg(&core::ops::Add::add),
|
||||||
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_SUB => set_reg(&core::ops::Sub::sub),
|
||||||
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_MUL => set_reg(&core::ops::Mul::mul),
|
||||||
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_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()),
|
RISCV_FP_SQRT => { self.fp_reg.set_reg(inst.rd, self.fp_reg.get_reg(inst.rs1).sqrt()); Ok(()) },
|
||||||
RISCV_FP_FSGN => {
|
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);
|
let local_float = self.fp_reg.get_reg(inst.rs1);
|
||||||
match inst.funct3 {
|
match inst.funct3 {
|
||||||
RISCV_FP_FSGN_J => if self.fp_reg.get_reg(inst.rs2) < 0f32 {
|
RISCV_FP_FSGN_J => if self.fp_reg.get_reg(inst.rs2) < 0f32 {
|
||||||
self.fp_reg.set_reg(inst.rd, -local_float)
|
self.fp_reg.set_reg(inst.rd, -local_float);
|
||||||
} else {
|
} else {
|
||||||
self.fp_reg.set_reg(inst.rd, local_float)
|
self.fp_reg.set_reg(inst.rd, local_float);
|
||||||
},
|
},
|
||||||
RISCV_FP_FSGN_JN => if self.fp_reg.get_reg(inst.rs2) < 0f32 {
|
RISCV_FP_FSGN_JN => if self.fp_reg.get_reg(inst.rs2) < 0f32 {
|
||||||
self.fp_reg.set_reg(inst.rd, local_float)
|
self.fp_reg.set_reg(inst.rd, local_float);
|
||||||
} else {
|
} else {
|
||||||
self.fp_reg.set_reg(inst.rd, -local_float)
|
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) ||
|
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.get_reg(inst.rs2) >= 0.0 && self.fp_reg.get_reg(inst.rs1) < 0.0) {
|
||||||
self.fp_reg.set_reg(inst.rd, -local_float)
|
self.fp_reg.set_reg(inst.rd, -local_float);
|
||||||
} else {
|
} else {
|
||||||
self.fp_reg.set_reg(inst.rd, local_float)
|
self.fp_reg.set_reg(inst.rd, local_float);
|
||||||
},
|
},
|
||||||
_ => panic!("this instruction ({}) doesn't exists", inst.value)
|
_ => Err(format!("Unreachable in fp_fsgn_instruction! Instruction was {:?}", inst))?
|
||||||
}
|
}
|
||||||
},
|
Ok(())
|
||||||
RISCV_FP_MINMAX => {
|
}
|
||||||
|
|
||||||
|
/// 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 r1 = self.fp_reg.get_reg(inst.rs1);
|
||||||
let r2 = self.fp_reg.get_reg(inst.rs2);
|
let r2 = self.fp_reg.get_reg(inst.rs2);
|
||||||
match inst.funct3 {
|
match inst.funct3 {
|
||||||
RISCV_FP_MINMAX_MIN => self.fp_reg.set_reg(inst.rd, if r1 < r2 {r1} else {r2}),
|
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}),
|
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)
|
_ => Err(format!("Unreachable in fp_minmax_instruction! Instruction was {:?}", inst))?
|
||||||
|
};
|
||||||
|
Ok(())
|
||||||
}
|
}
|
||||||
},
|
|
||||||
RISCV_FP_FCVTW => {
|
/// 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 {
|
if inst.rs2 == RISCV_FP_FCVTW_W {
|
||||||
self.int_reg.set_reg(inst.rd, self.fp_reg.get_reg(inst.rs1) as i64)
|
self.int_reg.set_reg(inst.rd, self.fp_reg.get_reg(inst.rs1) as i64)
|
||||||
} else {
|
} else {
|
||||||
self.int_reg.set_reg(inst.rd, (self.fp_reg.get_reg(inst.rs1) as u64) as i64)
|
self.int_reg.set_reg(inst.rd, (self.fp_reg.get_reg(inst.rs1) as u64) as i64)
|
||||||
}
|
}
|
||||||
},
|
Ok(())
|
||||||
RISCV_FP_FCVTS => {
|
}
|
||||||
|
|
||||||
|
/// 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 {
|
if inst.rs2 == RISCV_FP_FCVTS_W {
|
||||||
self.fp_reg.set_reg(inst.rd, self.int_reg.get_reg(inst.rs1) as f32);
|
self.fp_reg.set_reg(inst.rd, self.int_reg.get_reg(inst.rs1) as f32);
|
||||||
} else {
|
} else {
|
||||||
self.fp_reg.set_reg(inst.rd, (self.int_reg.get_reg(inst.rs1) as u32) as f32);
|
self.fp_reg.set_reg(inst.rd, (self.int_reg.get_reg(inst.rs1) as u32) as f32);
|
||||||
}
|
}
|
||||||
},
|
Ok(())
|
||||||
RISCV_FP_FMVW => self.fp_reg.set_reg(inst.rd, self.int_reg.get_reg(inst.rs1) as f32),
|
}
|
||||||
RISCV_FP_FMVXFCLASS => {
|
|
||||||
|
/// 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 {
|
if inst.funct3 == RISCV_FP_FMVXFCLASS_FMVX {
|
||||||
self.int_reg.set_reg(inst.rd, self.fp_reg.get_reg(inst.rs1) as i64);
|
self.int_reg.set_reg(inst.rd, self.fp_reg.get_reg(inst.rs1) as i64);
|
||||||
|
Ok(())
|
||||||
} else {
|
} else {
|
||||||
panic!("Fclass instruction is not handled in riscv simulator");
|
Err(format!("Unreachable in fp_fmvxfclass_instruction! Instruction was {:?}", inst))?
|
||||||
}
|
}
|
||||||
},
|
}
|
||||||
RISCV_FP_FCMP => {
|
|
||||||
|
/// Executes RISC-V floating point values comparaison instructions on the machine.
|
||||||
|
fn fp_fcmp_instruction(&mut self, inst: Instruction) -> Result<(), MachineError> {
|
||||||
match inst.funct3 {
|
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_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_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),
|
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)
|
_ => Err(format!("Unreachable in fp_fcmp_instruction match! Instruction was {:?}", inst))?
|
||||||
}
|
|
||||||
},
|
|
||||||
_ => panic!("this instruction ({}) doesn't exists", inst.value)
|
|
||||||
}
|
}
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user