♻️ Simplified fp_instruction
This commit is contained in:
parent
2e41758a52
commit
72f560f3ec
@ -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(())
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user