♻️ Started work on machine.rs refactoring

# Current changes

 - Crude error management
 - Readability improvements
 - Broke down one_instruction into smaller, more manageable methods
 - Added crude documentation
This commit is contained in:
François Autin 2023-03-23 20:05:46 +01:00
parent 87d90c394f
commit 43de76bd72
No known key found for this signature in database
GPG Key ID: 343F5D382E1DD77C

View File

@ -1,6 +1,6 @@
use std::{ops::{Add, Sub}, io::Write}; use std::{ops::{Add, Sub}, io::Write};
use crate::simulator::print; use crate::simulator::{print, error::MachineError};
use super::{decode::{Instruction, decode}, interrupt::Interrupt}; use super::{decode::{Instruction, decode}, interrupt::Interrupt};
use super::global::*; use super::global::*;
@ -230,28 +230,16 @@ impl Machine {
/// ///
/// - **machine** which contains a table of instructions /// - **machine** which contains a table of instructions
pub fn run(machine : &mut Machine){ pub fn run(machine : &mut Machine){
while Machine::one_instruction(machine) == 0 {} while let Ok(()) = Machine::one_instruction(machine) {}
println!("trace : \n{}", machine.registers_trace); println!("trace : \n{}", machine.registers_trace);
} }
/// execute the current instruction /// Execute the current instruction
/// ///
/// ### Parameters /// ### Parameters
/// ///
/// - **machine** which contains a table of instructions and a pc to the actual instruction /// - **machine** which contains a table of instructions and a pc to the actual instruction
pub fn one_instruction(machine :&mut Machine) -> i32 { pub fn one_instruction(machine :&mut Machine) -> Result<(), MachineError> {
let unsigned_reg1 : u64;
let unsigned_reg2 : u64;
let long_result : i128;
/*__int128 longResult;
int32_t local_data_a, local_data_b;
int64_t localLongResult;
uint32_t local_data_aUnsigned, local_data_bUnsigned;
int32_t localResult;
float localFloat;
uint64_t value;*/
if machine.main_memory.len() <= machine.pc as usize { if machine.main_memory.len() <= machine.pc as usize {
panic!("ERROR : number max of instructions rushed"); panic!("ERROR : number max of instructions rushed");
@ -274,23 +262,62 @@ impl Machine {
match inst.opcode { match inst.opcode {
RISCV_LUI => { RISCV_LUI => {
machine.int_reg.set_reg(inst.rd as usize, inst.imm31_12 as i64); machine.int_reg.set_reg(inst.rd as usize, inst.imm31_12 as i64);
Ok(())
}, },
RISCV_AUIPC => { RISCV_AUIPC => {
machine.int_reg.set_reg(inst.rd as usize,machine.pc as i64 - 4 + inst.imm31_12 as i64); machine.int_reg.set_reg(inst.rd as usize,machine.pc as i64 - 4 + inst.imm31_12 as i64);
Ok(())
}, },
RISCV_JAL => { RISCV_JAL => {
machine.int_reg.set_reg(inst.rd as usize, machine.pc as i64); machine.int_reg.set_reg(inst.rd as usize, machine.pc as i64);
machine.pc = (machine.pc as i64 + inst.imm21_1_signed as i64 - 4) as u64; machine.pc = (machine.pc as i64 + inst.imm21_1_signed as i64 - 4) as u64;
Ok(())
}, },
RISCV_JALR => { RISCV_JALR => {
let tmp = machine.pc; let tmp = machine.pc;
machine.pc = (machine.int_reg.get_reg(inst.rs1 as usize) + inst.imm12_I_signed as i64) as u64 & 0xfffffffe; machine.pc = (machine.int_reg.get_reg(inst.rs1 as usize) + inst.imm12_I_signed as i64) as u64 & 0xfffffffe;
machine.int_reg.set_reg(inst.rd as usize, tmp as i64); machine.int_reg.set_reg(inst.rd as usize, tmp as i64);
Ok(())
}, },
//******************************************************************************************
// Treatment for: BRANCH INSTRUCTIONS // Treatment for: BRANCH INSTRUCTIONS
RISCV_BR => { RISCV_BR => {
Self::branch_instruction(machine, inst)
},
// Treatment for: LOAD INSTRUCTIONS
RISCV_LD => {
Self::load_instruction(machine, inst)
},
// store instructions
RISCV_ST => {
Self::store_instruction(machine, inst)
},
// Treatment for: OPI INSTRUCTIONS
RISCV_OPI => {
Self::opi_instruction(machine, inst)
},
RISCV_OP => {
Self::op_instruction(machine, inst)
},
// Treatment for OPIW INSTRUCTIONS
RISCV_OPIW => {
Self::opiw_instruction(machine, inst)
},
// Treatment for: OPW INSTRUCTIONS
RISCV_OPW => Self::opw_instruction(machine, inst),
// Treatment for: Simple floating point extension
RISCV_FP => Self::fp_instruction(machine, inst),
// Treatment for: System instructions
RISCV_SYSTEM => {
// temporary return value to stop the loop of run
// before we can use system call
Err(MachineError::new(format!("{:x}: System opcode\npc: {:x}", inst.opcode, machine.pc).as_str()))
},
_ => Err(MachineError::new(format!("{:x}: Unknown opcode\npc: {:x}", inst.opcode, machine.pc).as_str()))
}
}
/// Treatement for Branch instructions
fn branch_instruction(machine: &mut Machine, inst: Instruction) -> Result<(), MachineError> {
match inst.funct3 { match inst.funct3 {
RISCV_BR_BEQ => { RISCV_BR_BEQ => {
if machine.int_reg.get_reg(inst.rs1 as usize) == machine.int_reg.get_reg(inst.rs2 as usize) { if machine.int_reg.get_reg(inst.rs1 as usize) == machine.int_reg.get_reg(inst.rs2 as usize) {
@ -326,11 +353,11 @@ impl Machine {
panic!("In BR switch case, this should never happen... Instr was {}", inst.value); panic!("In BR switch case, this should never happen... Instr was {}", inst.value);
} }
} }
}, Ok(())
}
//****************************************************************************************** /// Executes RISC-V Load Instructions on the machine
// Treatment for: LOAD INSTRUCTIONS fn load_instruction(machine: &mut Machine, inst: Instruction) -> Result<(), MachineError> {
RISCV_LD => {
match inst.funct3 { match inst.funct3 {
RISCV_LD_LB | RISCV_LD_LBU => { RISCV_LD_LB | RISCV_LD_LBU => {
let tmp = Self::read_memory(machine, 1, (machine.int_reg.get_reg(inst.rs1 as usize) + inst.imm12_I_signed as i64) as usize) as i64; let tmp = Self::read_memory(machine, 1, (machine.int_reg.get_reg(inst.rs1 as usize) + inst.imm12_I_signed as i64) as usize) as i64;
@ -348,157 +375,114 @@ impl Machine {
let tmp = Self::read_memory(machine, 8, (machine.int_reg.get_reg(inst.rs1 as usize) + inst.imm12_I_signed as i64) as usize) as i64; let tmp = Self::read_memory(machine, 8, (machine.int_reg.get_reg(inst.rs1 as usize) + inst.imm12_I_signed as i64) as usize) as i64;
machine.int_reg.set_reg(inst.rd as usize, tmp); machine.int_reg.set_reg(inst.rd as usize, tmp);
}, },
_ => { _ => panic!("In LD switch case, this should never happen... Instr was {}", inst.value)
panic!("In LD switch case, this should never happen... Instr was {}", inst.value);
} }
Ok(())
} }
},
// store instructions /// Executes RISC-V Store Instructions on the machine
RISCV_ST => { fn store_instruction(machine: &mut Machine, inst: Instruction) -> Result<(), MachineError> {
match inst.funct3 { match inst.funct3 {
RISCV_ST_STB => { RISCV_ST_STB => Self::write_memory(machine, 1, (machine.int_reg.get_reg(inst.rs1 as usize) + inst.imm12_S_signed as i64) as usize, machine.int_reg.get_reg(inst.rs2 as usize) as u64),
Self::write_memory(machine, 1, (machine.int_reg.get_reg(inst.rs1 as usize) + inst.imm12_S_signed as i64) as usize, machine.int_reg.get_reg(inst.rs2 as usize) as u64); RISCV_ST_STH => Self::write_memory(machine, 2, (machine.int_reg.get_reg(inst.rs1 as usize) + inst.imm12_S_signed as i64) as usize, machine.int_reg.get_reg(inst.rs2 as usize) as u64),
}, RISCV_ST_STW => Self::write_memory(machine, 4, (machine.int_reg.get_reg(inst.rs1 as usize) + inst.imm12_S_signed as i64) as usize, machine.int_reg.get_reg(inst.rs2 as usize) as u64),
RISCV_ST_STH => { RISCV_ST_STD => Self::write_memory(machine, 8, (machine.int_reg.get_reg(inst.rs1 as usize) + inst.imm12_S_signed as i64) as usize, machine.int_reg.get_reg(inst.rs2 as usize) as u64),
Self::write_memory(machine, 2, (machine.int_reg.get_reg(inst.rs1 as usize) + inst.imm12_S_signed as i64) as usize, machine.int_reg.get_reg(inst.rs2 as usize) as u64); _ => panic!("In ST switch case, this should never happen... Instr was {}", inst.value)
},
RISCV_ST_STW => {
Self::write_memory(machine, 4, (machine.int_reg.get_reg(inst.rs1 as usize) + inst.imm12_S_signed as i64) as usize, machine.int_reg.get_reg(inst.rs2 as usize) as u64);
},
RISCV_ST_STD => {
Self::write_memory(machine, 8, (machine.int_reg.get_reg(inst.rs1 as usize) + inst.imm12_S_signed as i64) as usize, machine.int_reg.get_reg(inst.rs2 as usize) as u64);
},
_ => {
panic!("In ST switch case, this should never happen... Instr was {}", inst.value);
} }
Ok(())
} }
}
//****************************************************************************************** /// Executes RISC-V Integer Register-Immediate Instructions on the machine
// Treatment for: OPI INSTRUCTIONS fn opi_instruction(machine: &mut Machine, inst: Instruction) -> Result<(), MachineError> {
RISCV_OPI => {
match inst.funct3 { match inst.funct3 {
RISCV_OPI_ADDI => { RISCV_OPI_ADDI => machine.int_reg.set_reg(inst.rd as usize, machine.int_reg.get_reg(inst.rs1 as usize) + inst.imm12_I_signed as i64),
machine.int_reg.set_reg(inst.rd as usize, machine.int_reg.get_reg(inst.rs1 as usize) + inst.imm12_I_signed as i64); RISCV_OPI_SLTI => machine.int_reg.set_reg(inst.rd as usize, (machine.int_reg.get_reg(inst.rs1 as usize) < inst.imm12_I_signed as i64) as i64),
}, RISCV_OPI_XORI => machine.int_reg.set_reg(inst.rd as usize, machine.int_reg.get_reg(inst.rs1 as usize) ^ inst.imm12_I_signed as i64),
RISCV_OPI_SLTI => { RISCV_OPI_ORI => machine.int_reg.set_reg(inst.rd as usize, machine.int_reg.get_reg(inst.rs1 as usize) | inst.imm12_I_signed as i64),
machine.int_reg.set_reg(inst.rd as usize, (machine.int_reg.get_reg(inst.rs1 as usize) < inst.imm12_I_signed as i64) as i64); RISCV_OPI_ANDI => machine.int_reg.set_reg(inst.rd as usize, machine.int_reg.get_reg(inst.rs1 as usize) & inst.imm12_I_signed as i64),
}, RISCV_OPI_SLLI => machine.int_reg.set_reg(inst.rd as usize, machine.int_reg.get_reg(inst.rs1 as usize) << inst.shamt),
RISCV_OPI_XORI => { RISCV_OPI_SRI => if inst.funct7_smaller == RISCV_OPI_SRI_SRLI {
machine.int_reg.set_reg(inst.rd as usize, machine.int_reg.get_reg(inst.rs1 as usize) ^ inst.imm12_I_signed as i64);
},
RISCV_OPI_ORI => {
machine.int_reg.set_reg(inst.rd as usize, machine.int_reg.get_reg(inst.rs1 as usize) | inst.imm12_I_signed as i64);
},
RISCV_OPI_ANDI => {
machine.int_reg.set_reg(inst.rd as usize, machine.int_reg.get_reg(inst.rs1 as usize) & inst.imm12_I_signed as i64);
},
RISCV_OPI_SLLI => {
machine.int_reg.set_reg(inst.rd as usize, machine.int_reg.get_reg(inst.rs1 as usize) << inst.shamt);
},
RISCV_OPI_SRI => {
if inst.funct7_smaller == RISCV_OPI_SRI_SRLI {
machine.int_reg.set_reg(inst.rd as usize, (machine.int_reg.get_reg(inst.rs1 as usize) >> inst.shamt) & machine.shiftmask[inst.shamt as usize] as i64); machine.int_reg.set_reg(inst.rd as usize, (machine.int_reg.get_reg(inst.rs1 as usize) >> inst.shamt) & machine.shiftmask[inst.shamt as usize] as i64);
} else { // SRAI } else { // SRAI
machine.int_reg.set_reg(inst.rd as usize, machine.int_reg.get_reg(inst.rs1 as usize) >> inst.shamt); machine.int_reg.set_reg(inst.rd as usize, machine.int_reg.get_reg(inst.rs1 as usize) >> inst.shamt);
}
}
_ => { panic!("In OPI switch case, this should never happen... Instr was %x\n {}", inst.value); }
}
}, },
_ => panic!("In OPI switch case, this should never happen... Instr was %x\n {}", inst.value)
}
Ok(())
}
RISCV_OP => { /// Executes simple RISC-V mathematical operations on the machine
fn op_instruction(machine: &mut Machine, inst: Instruction) -> Result<(), MachineError> {
let long_result: i128;
let unsigned_reg1: u64;
let unsigned_reg2: u64;
if inst.funct7 == 1 { if inst.funct7 == 1 {
match inst.funct3 { match inst.funct3 {
RISCV_OP_M_MUL => { RISCV_OP_M_MUL => {
long_result = (machine.int_reg.get_reg(inst.rs1 as usize) * machine.int_reg.get_reg(inst.rs2 as usize)) as i128; long_result = (machine.int_reg.get_reg(inst.rs1 as usize) * machine.int_reg.get_reg(inst.rs2 as usize)) as i128;
machine.int_reg.set_reg(inst.rd as usize, (long_result & 0xffffffffffffffff) as i64); machine.int_reg.set_reg(inst.rd as usize, (long_result & 0xffffffffffffffff) as i64)
}, },
RISCV_OP_M_MULH => { RISCV_OP_M_MULH => {
long_result = (machine.int_reg.get_reg(inst.rs1 as usize) * machine.int_reg.get_reg(inst.rs2 as usize)) as i128; long_result = (machine.int_reg.get_reg(inst.rs1 as usize) * machine.int_reg.get_reg(inst.rs2 as usize)) as i128;
machine.int_reg.set_reg(inst.rd as usize, ((long_result >> 64) & 0xffffffffffffffff) as i64); machine.int_reg.set_reg(inst.rd as usize, ((long_result >> 64) & 0xffffffffffffffff) as i64)
}, },
RISCV_OP_M_MULHSU => { RISCV_OP_M_MULHSU => {
unsigned_reg2 = machine.int_reg.get_reg(inst.rs2 as usize) as u64; unsigned_reg2 = machine.int_reg.get_reg(inst.rs2 as usize) as u64;
long_result = (machine.int_reg.get_reg(inst.rs1 as usize) as u64 * unsigned_reg2) as i128; long_result = (machine.int_reg.get_reg(inst.rs1 as usize) as u64 * unsigned_reg2) as i128;
machine.int_reg.set_reg(inst.rd as usize, ((long_result >> 64) & 0xffffffffffffffff) as i64); machine.int_reg.set_reg(inst.rd as usize, ((long_result >> 64) & 0xffffffffffffffff) as i64)
}, },
// VOIR CE QUE FAIT EXACTEMENT CE TRUC , PK on converve
/*
* VOIR SI LES CAST machine.int_reg[....] = i128*u64 as u32 FAUSSE RESULTAT (suit pas la logique du code c++)
* WHAT DA HECK
*/
RISCV_OP_M_MULHU => { RISCV_OP_M_MULHU => {
unsigned_reg1 = machine.int_reg.get_reg(inst.rs1 as usize) as u64; unsigned_reg1 = machine.int_reg.get_reg(inst.rs1 as usize) as u64;
unsigned_reg2 = machine.int_reg.get_reg(inst.rs2 as usize) as u64; unsigned_reg2 = machine.int_reg.get_reg(inst.rs2 as usize) as u64;
long_result = (unsigned_reg1 * unsigned_reg2) as i128; long_result = (unsigned_reg1 * unsigned_reg2) as i128;
machine.int_reg.set_reg(inst.rd as usize, ((long_result >> 64) & 0xffffffffffffffff) as i64); machine.int_reg.set_reg(inst.rd as usize, ((long_result >> 64) & 0xffffffffffffffff) as i64);
}, },
RISCV_OP_M_DIV => { RISCV_OP_M_DIV => machine.int_reg.set_reg(inst.rd as usize, machine.int_reg.get_reg(inst.rs1 as usize) / machine.int_reg.get_reg(inst.rs2 as usize)),
machine.int_reg.set_reg(inst.rd as usize, machine.int_reg.get_reg(inst.rs1 as usize) / machine.int_reg.get_reg(inst.rs2 as usize)); _ => panic!("RISCV_OP : funct7 = 1 (Multiplication) :: Error\n")
}
_ => {
panic!("RISCV_OP : funct7 = 1 (Multiplication) :: Error\n");
}
} }
} else { } else {
match inst.funct3 { match inst.funct3 {
RISCV_OP_ADD => { RISCV_OP_ADD => if inst.funct7 == RISCV_OP_ADD_ADD {
if inst.funct7 == RISCV_OP_ADD_ADD { machine.int_reg.set_reg(inst.rd as usize, machine.int_reg.get_reg(inst.rs1 as usize) + machine.int_reg.get_reg(inst.rs2 as usize))
machine.int_reg.set_reg(inst.rd as usize, machine.int_reg.get_reg(inst.rs1 as usize) + machine.int_reg.get_reg(inst.rs2 as usize));
} else { } else {
machine.int_reg.set_reg(inst.rd as usize, machine.int_reg.get_reg(inst.rs1 as usize) - machine.int_reg.get_reg(inst.rs2 as usize)); machine.int_reg.set_reg(inst.rd as usize, machine.int_reg.get_reg(inst.rs1 as usize) - machine.int_reg.get_reg(inst.rs2 as usize))
}
}, },
RISCV_OP_SLL => { RISCV_OP_SLL => machine.int_reg.set_reg(inst.rd as usize, machine.int_reg.get_reg(inst.rs1 as usize) << (machine.int_reg.get_reg(inst.rs2 as usize) & 0x3f)),
machine.int_reg.set_reg(inst.rd as usize, machine.int_reg.get_reg(inst.rs1 as usize) << (machine.int_reg.get_reg(inst.rs2 as usize) & 0x3f)); RISCV_OP_SLT => if machine.int_reg.get_reg(inst.rs1 as usize) < machine.int_reg.get_reg(inst.rs2 as usize) {
}, machine.int_reg.set_reg(inst.rd as usize, 1)
RISCV_OP_SLT => {
if machine.int_reg.get_reg(inst.rs1 as usize) < machine.int_reg.get_reg(inst.rs2 as usize) {
machine.int_reg.set_reg(inst.rd as usize, 1);
} else { } else {
machine.int_reg.set_reg(inst.rd as usize, 0); machine.int_reg.set_reg(inst.rd as usize, 0)
}
}, },
RISCV_OP_SLTU => { RISCV_OP_SLTU => {
unsigned_reg1 = machine.int_reg.get_reg(inst.rs1 as usize) as u64; unsigned_reg1 = machine.int_reg.get_reg(inst.rs1 as usize) as u64;
unsigned_reg2 = machine.int_reg.get_reg(inst.rs2 as usize) as u64; unsigned_reg2 = machine.int_reg.get_reg(inst.rs2 as usize) as u64;
if unsigned_reg1 < unsigned_reg2 { if unsigned_reg1 < unsigned_reg2 {
machine.int_reg.set_reg(inst.rd as usize, 1); machine.int_reg.set_reg(inst.rd as usize, 1)
} else { } else {
machine.int_reg.set_reg(inst.rd as usize, 0); machine.int_reg.set_reg(inst.rd as usize, 0)
} }
}, },
RISCV_OP_XOR => { RISCV_OP_XOR => machine.int_reg.set_reg(inst.rd as usize, machine.int_reg.get_reg(inst.rs1 as usize) ^ machine.int_reg.get_reg(inst.rs2 as usize)),
machine.int_reg.set_reg(inst.rd as usize, machine.int_reg.get_reg(inst.rs1 as usize) ^ machine.int_reg.get_reg(inst.rs2 as usize)); RISCV_OP_SR => machine.int_reg.set_reg(inst.rd as usize, machine.int_reg.get_reg(inst.rs1 as usize) >> machine.int_reg.get_reg(inst.rs2 as usize)), // RISCV_OP_SR_SRL inaccessible
}, RISCV_OP_OR => machine.int_reg.set_reg(inst.rd as usize, machine.int_reg.get_reg(inst.rs1 as usize) | machine.int_reg.get_reg(inst.rs2 as usize)),
RISCV_OP_SR => { RISCV_OP_AND => machine.int_reg.set_reg(inst.rd as usize, machine.int_reg.get_reg(inst.rs1 as usize) & machine.int_reg.get_reg(inst.rs2 as usize)),
// RISCV_OP_SR_SRL inaccessible _ => panic!("RISCV_OP undefined case\n")
machine.int_reg.set_reg(inst.rd as usize, machine.int_reg.get_reg(inst.rs1 as usize) >> machine.int_reg.get_reg(inst.rs2 as usize));
},
RISCV_OP_OR => {
machine.int_reg.set_reg(inst.rd as usize, machine.int_reg.get_reg(inst.rs1 as usize) | machine.int_reg.get_reg(inst.rs2 as usize));
},
RISCV_OP_AND => {
machine.int_reg.set_reg(inst.rd as usize, machine.int_reg.get_reg(inst.rs1 as usize) & machine.int_reg.get_reg(inst.rs2 as usize));
},
_ => {
panic!("RISCV_OP undefined case\n");
} }
}//LA
} }
}, Ok(())
//****************************************************************************************** }
// Treatment for OPIW INSTRUCTIONS
RISCV_OPIW => { /// Exectutes simple RISC-V *iw instructions on the machine
fn opiw_instruction(machine: &mut Machine, inst: Instruction) -> Result<(), MachineError> {
let local_data = machine.int_reg.get_reg(inst.rs1 as usize); let local_data = machine.int_reg.get_reg(inst.rs1 as usize);
match inst.funct3 { match inst.funct3 {
RISCV_OPIW_ADDIW => { RISCV_OPIW_ADDIW => {
let result = local_data + inst.imm12_I_signed as i64; let result = local_data + inst.imm12_I_signed as i64;
machine.int_reg.set_reg(inst.rd as usize, result); machine.int_reg.set_reg(inst.rd as usize, result)
}, },
RISCV_OPIW_SLLIW => { RISCV_OPIW_SLLIW => {
let result = local_data << inst.shamt; let result = local_data << inst.shamt;
machine.int_reg.set_reg(inst.rd as usize, result); machine.int_reg.set_reg(inst.rd as usize, result)
}, },
RISCV_OPIW_SRW => { RISCV_OPIW_SRW => {
let result = if inst.funct7 == RISCV_OPIW_SRW_SRLIW { let result = if inst.funct7 == RISCV_OPIW_SRW_SRLIW {
@ -506,16 +490,15 @@ impl Machine {
} else { // SRAIW } else { // SRAIW
local_data >> inst.shamt local_data >> inst.shamt
}; };
machine.int_reg.set_reg(inst.rd as usize, result); machine.int_reg.set_reg(inst.rd as usize, result)
}, },
_ => { _ => panic!("In OPI switch case, this should never happen... Instr was {}\n", inst.value),
panic!("In OPI switch case, this should never happen... Instr was {}\n", inst.value);
} }
Ok(())
} }
},
//****************************************************************************************** /// Executes simple RISC-V *w instructions on the machine
// Treatment for: OPW INSTRUCTIONS fn opw_instruction(machine: &mut Machine, inst: Instruction) -> Result<(), MachineError> {
RISCV_OPW => {
if inst.funct7 == 1 { // rv64m if inst.funct7 == 1 { // rv64m
let local_data_a = machine.int_reg.get_reg(inst.rs1 as usize) & 0xffffffff; let local_data_a = machine.int_reg.get_reg(inst.rs1 as usize) & 0xffffffff;
let local_data_b = machine.int_reg.get_reg(inst.rs2 as usize) & 0xffffffff; let local_data_b = machine.int_reg.get_reg(inst.rs2 as usize) & 0xffffffff;
@ -524,122 +507,78 @@ impl Machine {
// Match case for multiplication operations (in standard extension RV32M) // Match case for multiplication operations (in standard extension RV32M)
match inst.funct3 { match inst.funct3 {
RISCV_OPW_M_MULW => { RISCV_OPW_M_MULW => machine.int_reg.set_reg(inst.rd as usize, local_data_a * local_data_b),
machine.int_reg.set_reg(inst.rd as usize, local_data_a * local_data_b); RISCV_OPW_M_DIVW => machine.int_reg.set_reg(inst.rd as usize, local_data_a / local_data_b),
}, RISCV_OPW_M_DIVUW => machine.int_reg.set_reg(inst.rd as usize, local_data_a_unsigned / local_data_b_unsigned),
RISCV_OPW_M_DIVW => { RISCV_OPW_M_REMW => machine.int_reg.set_reg(inst.rd as usize, local_data_a % local_data_b),
machine.int_reg.set_reg(inst.rd as usize, local_data_a / local_data_b); RISCV_OPW_M_REMUW => machine.int_reg.set_reg(inst.rd as usize, local_data_a_unsigned % local_data_b_unsigned),
}, _ => panic!("this instruction ({}) doesn't exists", inst.value)
RISCV_OPW_M_DIVUW => {
machine.int_reg.set_reg(inst.rd as usize, local_data_a_unsigned / local_data_b_unsigned);
},
RISCV_OPW_M_REMW => {
machine.int_reg.set_reg(inst.rd as usize, local_data_a % local_data_b);
},
RISCV_OPW_M_REMUW => {
machine.int_reg.set_reg(inst.rd as usize, local_data_a_unsigned % local_data_b_unsigned);
},
_ => {
panic!("this instruction ({}) doesn't exists", inst.value);
}
} }
} else { // others rv64 OPW operations } else { // others rv64 OPW operations
let local_dataa = machine.int_reg.get_reg(inst.rs1 as usize) & 0xffffffff; let local_dataa = machine.int_reg.get_reg(inst.rs1 as usize) & 0xffffffff;
let local_datab = machine.int_reg.get_reg(inst.rs2 as usize) & 0xffffffff; let local_datab = machine.int_reg.get_reg(inst.rs2 as usize) & 0xffffffff;
// Match case for base OP operation // Match case for base OP operation
match inst.funct3 { match inst.funct3 {
RISCV_OPW_ADDSUBW => { RISCV_OPW_ADDSUBW => if inst.funct7 == RISCV_OPW_ADDSUBW_ADDW {
if inst.funct7 == RISCV_OPW_ADDSUBW_ADDW {
machine.int_reg.set_reg(inst.rd as usize, local_dataa + local_datab); machine.int_reg.set_reg(inst.rd as usize, local_dataa + local_datab);
} else { // SUBW } else { // SUBW
machine.int_reg.set_reg(inst.rd as usize, local_dataa - local_datab); machine.int_reg.set_reg(inst.rd as usize, local_dataa - local_datab);
}
}, },
RISCV_OPW_SLLW => { RISCV_OPW_SLLW => machine.int_reg.set_reg(inst.rd as usize, local_dataa << (local_datab & 0x1f)),
machine.int_reg.set_reg(inst.rd as usize, local_dataa << (local_datab & 0x1f)); RISCV_OPW_SRW => if inst.funct7 == RISCV_OPW_SRW_SRLW {
}, machine.int_reg.set_reg(inst.rd as usize, local_dataa >> (local_datab & 0x1f) & machine.shiftmask[32 + local_datab as usize] as i64)
RISCV_OPW_SRW => {
if inst.funct7 == RISCV_OPW_SRW_SRLW {
machine.int_reg.set_reg(inst.rd as usize, local_dataa >> (local_datab & 0x1f) & machine.shiftmask[32 + local_datab as usize] as i64);
} else { // SRAW } else { // SRAW
machine.int_reg.set_reg(inst.rd as usize, local_dataa >> (local_datab & 0x1f)); machine.int_reg.set_reg(inst.rd as usize, local_dataa >> (local_datab & 0x1f))
}
}, },
_ => { _ => panic!("this instruction ({}) doesn't exists", inst.value)
panic!("this instruction ({}) doesn't exists", inst.value);
} }
} }
Ok(())
} }
},
//****************************************************************************************** /// Executes simple RISC-V floating point instructions on the machine
// Treatment for: Simple floating point extension fn fp_instruction(machine: &mut Machine, inst: Instruction) -> Result<(), MachineError> {
RISCV_FP => {
match inst.funct7 { match inst.funct7 {
RISCV_FP_ADD => { RISCV_FP_ADD => machine.fp_reg.set_reg(inst.rd as usize, machine.fp_reg.get_reg(inst.rs1 as usize) + machine.fp_reg.get_reg(inst.rs2 as usize)),
machine.fp_reg.set_reg(inst.rd as usize, machine.fp_reg.get_reg(inst.rs1 as usize) + machine.fp_reg.get_reg(inst.rs2 as usize)); RISCV_FP_SUB => machine.fp_reg.set_reg(inst.rd as usize, machine.fp_reg.get_reg(inst.rs1 as usize) - machine.fp_reg.get_reg(inst.rs2 as usize)),
}, RISCV_FP_MUL => machine.fp_reg.set_reg(inst.rd as usize, machine.fp_reg.get_reg(inst.rs1 as usize) * machine.fp_reg.get_reg(inst.rs2 as usize)),
RISCV_FP_SUB => { RISCV_FP_DIV => machine.fp_reg.set_reg(inst.rd as usize, machine.fp_reg.get_reg(inst.rs1 as usize) / machine.fp_reg.get_reg(inst.rs2 as usize)),
machine.fp_reg.set_reg(inst.rd as usize, machine.fp_reg.get_reg(inst.rs1 as usize) - machine.fp_reg.get_reg(inst.rs2 as usize)); RISCV_FP_SQRT => machine.fp_reg.set_reg(inst.rd as usize, machine.fp_reg.get_reg(inst.rs1 as usize).sqrt()),
},
RISCV_FP_MUL => {
machine.fp_reg.set_reg(inst.rd as usize, machine.fp_reg.get_reg(inst.rs1 as usize) * machine.fp_reg.get_reg(inst.rs2 as usize));
},
RISCV_FP_DIV => {
machine.fp_reg.set_reg(inst.rd as usize, machine.fp_reg.get_reg(inst.rs1 as usize) / machine.fp_reg.get_reg(inst.rs2 as usize));
},
RISCV_FP_SQRT => {
machine.fp_reg.set_reg(inst.rd as usize, machine.fp_reg.get_reg(inst.rs1 as usize).sqrt());
},
RISCV_FP_FSGN => { RISCV_FP_FSGN => {
let local_float = machine.fp_reg.get_reg(inst.rs1 as usize); let local_float = machine.fp_reg.get_reg(inst.rs1 as usize);
match inst.funct3 { match inst.funct3 {
RISCV_FP_FSGN_J => { RISCV_FP_FSGN_J => if machine.fp_reg.get_reg(inst.rs2 as usize) < 0f32 {
if machine.fp_reg.get_reg(inst.rs2 as usize) < 0f32 { machine.fp_reg.set_reg(inst.rd as usize, -local_float)
machine.fp_reg.set_reg(inst.rd as usize, -local_float);
} else { } else {
machine.fp_reg.set_reg(inst.rd as usize, local_float); machine.fp_reg.set_reg(inst.rd as usize, local_float)
} },
} RISCV_FP_FSGN_JN => if machine.fp_reg.get_reg(inst.rs2 as usize) < 0f32 {
RISCV_FP_FSGN_JN => { machine.fp_reg.set_reg(inst.rd as usize, local_float)
if machine.fp_reg.get_reg(inst.rs2 as usize) < 0f32 {
machine.fp_reg.set_reg(inst.rd as usize, local_float);
} else { } else {
machine.fp_reg.set_reg(inst.rd as usize, -local_float); machine.fp_reg.set_reg(inst.rd as usize, -local_float)
} },
} RISCV_FP_FSGN_JX => if (machine.fp_reg.get_reg(inst.rs2 as usize) < 0.0 && machine.fp_reg.get_reg(inst.rs1 as usize) >= 0.0) || (machine.fp_reg.get_reg(inst.rs2 as usize) >= 0.0 && machine.fp_reg.get_reg(inst.rs1 as usize) < 0.0) {
RISCV_FP_FSGN_JX => { machine.fp_reg.set_reg(inst.rd as usize, -local_float)
if (machine.fp_reg.get_reg(inst.rs2 as usize) < 0.0 && machine.fp_reg.get_reg(inst.rs1 as usize) >= 0.0) || (machine.fp_reg.get_reg(inst.rs2 as usize) >= 0.0 && machine.fp_reg.get_reg(inst.rs1 as usize) < 0.0) {
machine.fp_reg.set_reg(inst.rd as usize, -local_float);
} else { } else {
machine.fp_reg.set_reg(inst.rd as usize, local_float); machine.fp_reg.set_reg(inst.rd as usize, local_float)
} },
} _ => panic!("this instruction ({}) doesn't exists", inst.value)
_ => {
panic!("this instruction ({}) doesn't exists", inst.value);
}
} }
}, },
RISCV_FP_MINMAX => { RISCV_FP_MINMAX => {
let r1 = machine.fp_reg.get_reg(inst.rs1 as usize); let r1 = machine.fp_reg.get_reg(inst.rs1 as usize);
let r2 = machine.fp_reg.get_reg(inst.rs2 as usize); let r2 = machine.fp_reg.get_reg(inst.rs2 as usize);
match inst.funct3 { match inst.funct3 {
RISCV_FP_MINMAX_MIN => { RISCV_FP_MINMAX_MIN => machine.fp_reg.set_reg(inst.rd as usize, if r1 < r2 {r1} else {r2}),
machine.fp_reg.set_reg(inst.rd as usize, if r1 < r2 {r1} else {r2}); RISCV_FP_MINMAX_MAX => machine.fp_reg.set_reg(inst.rd as usize, if r1 > r2 {r1} else {r2}),
}, _ => panic!("this instruction ({}) doesn't exists", inst.value)
RISCV_FP_MINMAX_MAX => {
machine.fp_reg.set_reg(inst.rd as usize, if r1 > r2 {r1} else {r2});
},
_ => {
panic!("this instruction ({}) doesn't exists", inst.value);
}
} }
}, },
RISCV_FP_FCVTW => { RISCV_FP_FCVTW => {
if inst.rs2 == RISCV_FP_FCVTW_W { if inst.rs2 == RISCV_FP_FCVTW_W {
machine.int_reg.set_reg(inst.rd as usize, machine.fp_reg.get_reg(inst.rs1 as usize) as i64); machine.int_reg.set_reg(inst.rd as usize, machine.fp_reg.get_reg(inst.rs1 as usize) as i64)
} else { } else {
machine.int_reg.set_reg(inst.rd as usize, (machine.fp_reg.get_reg(inst.rs1 as usize) as u64) as i64); machine.int_reg.set_reg(inst.rd as usize, (machine.fp_reg.get_reg(inst.rs1 as usize) as u64) as i64)
} }
}, },
RISCV_FP_FCVTS => { RISCV_FP_FCVTS => {
@ -649,9 +588,7 @@ impl Machine {
machine.fp_reg.set_reg(inst.rd as usize, (machine.int_reg.get_reg(inst.rs1 as usize) as u32) as f32); machine.fp_reg.set_reg(inst.rd as usize, (machine.int_reg.get_reg(inst.rs1 as usize) as u32) as f32);
} }
}, },
RISCV_FP_FMVW => { RISCV_FP_FMVW => machine.fp_reg.set_reg(inst.rd as usize, machine.int_reg.get_reg(inst.rs1 as usize) as f32),
machine.fp_reg.set_reg(inst.rd as usize, machine.int_reg.get_reg(inst.rs1 as usize) as f32);
},
RISCV_FP_FMVXFCLASS => { RISCV_FP_FMVXFCLASS => {
if inst.funct3 == RISCV_FP_FMVXFCLASS_FMVX { if inst.funct3 == RISCV_FP_FMVXFCLASS_FMVX {
machine.int_reg.set_reg(inst.rd as usize, machine.fp_reg.get_reg(inst.rs1 as usize) as i64); machine.int_reg.set_reg(inst.rd as usize, machine.fp_reg.get_reg(inst.rs1 as usize) as i64);
@ -661,35 +598,15 @@ impl Machine {
}, },
RISCV_FP_FCMP => { RISCV_FP_FCMP => {
match inst.funct3 { match inst.funct3 {
RISCV_FP_FCMP_FEQ => { RISCV_FP_FCMP_FEQ => machine.int_reg.set_reg(inst.rd as usize, (machine.fp_reg.get_reg(inst.rs1 as usize) == machine.fp_reg.get_reg(inst.rs2 as usize)) as i64),
machine.int_reg.set_reg(inst.rd as usize, (machine.fp_reg.get_reg(inst.rs1 as usize) == machine.fp_reg.get_reg(inst.rs2 as usize)) as i64); RISCV_FP_FCMP_FLT => machine.int_reg.set_reg(inst.rd as usize, (machine.fp_reg.get_reg(inst.rs1 as usize) < machine.fp_reg.get_reg(inst.rs2 as usize)) as i64),
}, RISCV_FP_FCMP_FLE => machine.int_reg.set_reg(inst.rd as usize, (machine.fp_reg.get_reg(inst.rs1 as usize) <= machine.fp_reg.get_reg(inst.rs2 as usize)) as i64),
RISCV_FP_FCMP_FLT => { _ => panic!("this instruction ({}) doesn't exists", inst.value)
machine.int_reg.set_reg(inst.rd as usize, (machine.fp_reg.get_reg(inst.rs1 as usize) < machine.fp_reg.get_reg(inst.rs2 as usize)) as i64);
},
RISCV_FP_FCMP_FLE => {
machine.int_reg.set_reg(inst.rd as usize, (machine.fp_reg.get_reg(inst.rs1 as usize) <= machine.fp_reg.get_reg(inst.rs2 as usize)) as i64);
},
_ => {
panic!("this instruction ({}) doesn't exists", inst.value);
}
} }
}, },
_ => { _ => panic!("this instruction ({}) doesn't exists", inst.value)
panic!("this instruction ({}) doesn't exists", inst.value);
} }
} Ok(())
}
RISCV_SYSTEM => {
// temporary return value to stop the loop of run
// before we can use system call
return 1;
}
_ => { panic!("{:x} opcode non géré pc : {:x}", inst.opcode, machine.pc)},
}
0
} }
/// print memory FOR DEBUG /// print memory FOR DEBUG