2023-01-11 14:58:12 +01:00
use super ::{ decode ::{ Instruction , decode } , print ::* } ;
2022-11-09 15:59:05 +01:00
2022-11-23 16:04:21 +01:00
/// doit disparaitre
2022-11-15 21:21:24 +01:00
const MEM_SIZE : usize = 4096 ;
2022-11-09 15:59:05 +01:00
pub struct Machine {
2022-11-23 16:29:02 +01:00
pub pc : u64 ,
2022-11-23 18:04:35 +01:00
pub int_reg : [ i64 ; 32 ] ,
2022-11-23 16:29:02 +01:00
pub instructions : [ u64 ; 100 ] ,
2022-11-16 17:59:09 +01:00
pub main_memory : [ u8 ; MEM_SIZE ] ,
2022-11-23 16:29:02 +01:00
pub shiftmask : [ u64 ; 64 ]
2022-11-15 21:21:24 +01:00
// futur taille à calculer int memSize = g_cfg->NumPhysPages * g_cfg->PageSize;
//creer une struct cfg(configuration) qui s'initialise avec valeur dans un fichier cfg
2022-11-09 15:59:05 +01:00
}
impl Machine {
2022-11-09 16:47:26 +01:00
pub fn _init_machine ( ) -> Machine {
2022-11-23 16:29:02 +01:00
let mut shiftmask : [ u64 ; 64 ] = [ 0 ; 64 ] ;
let mut value : u64 = 0xffffffff ;
2022-11-16 17:59:09 +01:00
2022-11-23 16:29:02 +01:00
value = ( value < < 32 ) + value ;
2023-01-11 15:04:54 +01:00
for item in & mut shiftmask {
* item = value ;
2023-01-11 15:34:12 +01:00
value > > = 1 ;
2022-11-16 17:59:09 +01:00
}
2022-11-09 15:59:05 +01:00
Machine {
2022-11-09 16:47:26 +01:00
pc : 0 ,
instructions : [ 0 ; 100 ] ,
2022-11-15 21:21:24 +01:00
int_reg : [ 0 ; 32 ] ,
2022-11-16 17:59:09 +01:00
main_memory : [ 0 ; MEM_SIZE ] ,
2023-01-11 15:04:54 +01:00
shiftmask
2022-11-09 15:59:05 +01:00
}
}
2022-11-09 16:47:26 +01:00
2022-11-23 18:04:35 +01:00
/// Read from main memory of the machine
///
2023-01-18 15:03:58 +01:00
/// `panic!` when size is not 1, 2, 4 or 8
///
2022-11-23 18:04:35 +01:00
/// ### Parameters
///
/// - **machine** which contains the main memory
/// - **size** the number of bytes to read (1, 2, 4, 8)
/// - **address** in the memory to read
pub fn read_memory ( machine : & mut Machine , size : i32 , address : usize ) -> u64 {
2023-01-18 15:03:58 +01:00
if ! [ 1 , 2 , 4 , 8 ] . contains ( & size ) {
2023-01-11 15:34:51 +01:00
panic! ( " ERROR read_memory : wrong size parameter {} , must be (1, 2, 4 or 8) " , size ) ;
2022-11-23 18:04:35 +01:00
}
2023-01-18 15:03:58 +01:00
let mut ret : u64 = 0 ;
for i in 0 .. size {
2023-01-11 15:04:54 +01:00
ret < < = 8 ;
2023-01-18 15:03:58 +01:00
ret + = machine . main_memory [ address + i as usize ] as u64 ;
2022-11-23 18:04:35 +01:00
}
2023-01-11 15:04:54 +01:00
ret
2022-11-23 18:04:35 +01:00
}
2022-11-21 13:21:48 +01:00
2023-01-16 19:12:20 +01:00
/// Write to the main memory of the machine
///
2023-01-18 15:03:58 +01:00
/// `panic!` when size is not 1, 2, 4 or 8
///
/// ### Parameters
///
/// - **machine** contains the memory
/// - **size** the number of bytes to write (1, 2, 4 or 8)
/// - **address** the address to write to
/// - **value** data to be written
pub fn write_memory ( machine : & mut Machine , size : i32 , address : usize , value : u64 ) {
if ! [ 1 , 2 , 4 , 8 ] . contains ( & size ) {
2023-01-16 19:12:20 +01:00
panic! ( " ERROR write_memory: WRONG `size` PARAMETER ( {} ), must be 1, 2, 4 or 8 " , size )
}
2023-01-18 15:03:58 +01:00
for i in 0 .. size as usize {
2023-01-18 17:42:56 +01:00
let inv_i = size as usize - i - 1 ;
machine . main_memory [ address + i as usize ] = ( ( value & 0xff < < ( 8 * inv_i ) ) > > ( inv_i * 8 ) ) as u8 ;
2023-01-18 15:03:58 +01:00
}
2023-01-16 19:12:20 +01:00
}
2022-11-23 16:04:21 +01:00
/// Execute the instructions table of a machine putted in param
///
/// ### Parameters
///
/// - **machine** which contains a table of instructions
2022-11-21 13:17:42 +01:00
pub fn run ( machine : Machine ) {
let mut m = machine ;
loop {
Machine ::one_instruction ( & mut m ) ;
}
}
2022-11-23 16:04:21 +01:00
/// execute the current instruction
///
/// ### Parameters
///
/// - **machine** which contains a table of instructions and a pc to the actual instruction
2022-11-16 16:52:52 +01:00
pub fn one_instruction ( machine :& mut Machine ) {
2022-11-15 21:21:24 +01:00
2023-01-11 15:04:54 +01:00
let unsigned_reg1 : u64 ;
let unsigned_reg2 : u64 ;
let long_result : i128 ;
2022-11-16 17:48:55 +01:00
/* __int128 longResult;
2023-01-11 15:04:54 +01:00
int32_t local_data_a , local_data_b ;
2022-11-16 17:48:55 +01:00
int64_t localLongResult ;
2023-01-11 15:04:54 +01:00
uint32_t local_data_aUnsigned , local_data_bUnsigned ;
2022-11-16 17:48:55 +01:00
int32_t localResult ;
float localFloat ;
uint64_t value ; * /
2022-11-15 21:21:24 +01:00
2022-11-16 15:48:46 +01:00
if machine . instructions . len ( ) < = machine . pc as usize {
2022-11-09 16:47:26 +01:00
println! ( " ERROR : number max of instructions rushed " ) ;
2022-11-16 16:52:52 +01:00
return ;
2022-11-09 16:47:26 +01:00
}
2022-11-09 17:35:16 +01:00
2022-11-09 16:47:26 +01:00
let inst : Instruction = decode ( machine . instructions [ machine . pc as usize ] ) ;
2022-11-15 21:21:24 +01:00
2022-12-07 17:09:53 +01:00
2022-11-15 21:21:24 +01:00
match inst . opcode {
2022-11-09 16:47:26 +01:00
RISCV_LUI = > {
2022-11-23 18:04:35 +01:00
machine . int_reg [ inst . rd as usize ] = inst . imm31_12 as i64 ;
2022-11-09 16:47:26 +01:00
} ,
2022-11-23 16:29:02 +01:00
RISCV_AUIPC = > {
2022-11-23 18:04:35 +01:00
machine . int_reg [ inst . rd as usize ] = machine . pc as i64 - 4 + inst . imm31_12 as i64 ;
2022-11-23 16:29:02 +01:00
} ,
RISCV_JAL = > {
2022-11-23 18:04:35 +01:00
machine . int_reg [ inst . rd as usize ] = machine . pc as i64 ;
2022-11-23 16:29:02 +01:00
machine . pc + = inst . imm21_1_signed as u64 - 4 ;
} ,
RISCV_JALR = > {
let tmp = machine . pc ;
2022-11-23 18:04:35 +01:00
machine . pc = ( machine . int_reg [ inst . rs1 as usize ] as u64 + inst . imm12_I_signed as u64 ) & 0xfffffffe ;
machine . int_reg [ inst . rd as usize ] = tmp as i64 ;
} ,
//******************************************************************************************
// Treatment for: BRANCH INSTRUCTIONS
RISCV_BR = > {
match inst . funct3 {
RISCV_BR_BEQ = > {
if machine . int_reg [ inst . rs1 as usize ] = = machine . int_reg [ inst . rs2 as usize ] {
machine . pc + = inst . imm13_signed as u64 - 4 ;
}
} ,
RISCV_BR_BNE = > {
if machine . int_reg [ inst . rs1 as usize ] ! = machine . int_reg [ inst . rs2 as usize ] {
machine . pc + = inst . imm13_signed as u64 - 4 ;
}
} ,
2023-01-11 15:04:54 +01:00
RISCV_BR_BLT = > {
2022-11-23 18:04:35 +01:00
if machine . int_reg [ inst . rs1 as usize ] < machine . int_reg [ inst . rs2 as usize ] {
machine . pc + = inst . imm13_signed as u64 - 4 ;
}
} ,
2023-01-11 15:04:54 +01:00
RISCV_BR_BGE = > {
2022-11-23 18:04:35 +01:00
if machine . int_reg [ inst . rs1 as usize ] > = machine . int_reg [ inst . rs2 as usize ] {
machine . pc + = inst . imm13_signed as u64 - 4 ;
}
} ,
2023-01-11 15:04:54 +01:00
RISCV_BR_BLTU = > {
2022-11-23 18:04:35 +01:00
if machine . int_reg [ inst . rs1 as usize ] < machine . int_reg [ inst . rs2 as usize ] {
machine . pc + = inst . imm13_signed as u64 - 4 ;
}
} ,
2023-01-11 15:04:54 +01:00
RISCV_BR_BGEU = > {
2022-11-23 18:04:35 +01:00
if machine . int_reg [ inst . rs1 as usize ] > = machine . int_reg [ inst . rs2 as usize ] {
machine . pc + = inst . imm13_signed as u64 - 4 ;
}
} ,
_ = > {
2023-01-16 19:12:20 +01:00
panic! ( " In BR switch case, this should never happen... Instr was {} " , inst . value ) ;
2022-11-23 18:04:35 +01:00
}
}
} ,
//******************************************************************************************
// Treatment for: LOAD INSTRUCTIONS
RISCV_LD = > {
match inst . funct3 {
RISCV_LD_LB = > {
2023-01-18 15:12:25 +01:00
machine . int_reg [ inst . rd as usize ] = Self ::read_memory ( machine , 1 , ( machine . int_reg [ inst . rs1 as usize ] + inst . imm12_I_signed as i64 ) as usize ) as i64 ;
2022-11-23 18:04:35 +01:00
} ,
RISCV_LD_LH = > {
2023-01-18 15:12:25 +01:00
machine . int_reg [ inst . rd as usize ] = Self ::read_memory ( machine , 2 , ( machine . int_reg [ inst . rs1 as usize ] + inst . imm12_I_signed as i64 ) as usize ) as i64 ;
2022-11-23 18:04:35 +01:00
} ,
RISCV_LD_LW = > {
2023-01-18 15:12:25 +01:00
machine . int_reg [ inst . rd as usize ] = Self ::read_memory ( machine , 4 , ( machine . int_reg [ inst . rs1 as usize ] + inst . imm12_I_signed as i64 ) as usize ) as i64 ;
2022-11-23 18:04:35 +01:00
} ,
RISCV_LD_LD = > {
2023-01-18 15:12:25 +01:00
machine . int_reg [ inst . rd as usize ] = Self ::read_memory ( machine , 8 , ( machine . int_reg [ inst . rs1 as usize ] + inst . imm12_I_signed as i64 ) as usize ) as i64 ;
2022-11-23 18:04:35 +01:00
} ,
// same thing three opration ?
RISCV_LD_LBU = > {
2023-01-18 15:12:25 +01:00
machine . int_reg [ inst . rd as usize ] = Self ::read_memory ( machine , 1 , ( machine . int_reg [ inst . rs1 as usize ] + inst . imm12_I_signed as i64 ) as usize ) as i64 ;
2022-11-23 18:04:35 +01:00
} ,
RISCV_LD_LHU = > {
2023-01-18 15:12:25 +01:00
machine . int_reg [ inst . rd as usize ] = Self ::read_memory ( machine , 2 , ( machine . int_reg [ inst . rs1 as usize ] + inst . imm12_I_signed as i64 ) as usize ) as i64 ;
2022-11-23 18:04:35 +01:00
} ,
RISCV_LD_LWU = > {
2023-01-18 15:12:25 +01:00
machine . int_reg [ inst . rd as usize ] = Self ::read_memory ( machine , 4 , ( machine . int_reg [ inst . rs1 as usize ] + inst . imm12_I_signed as i64 ) as usize ) as i64 ;
2022-11-23 18:04:35 +01:00
} ,
_ = > {
2023-01-16 19:12:20 +01:00
panic! ( " In LD switch case, this should never happen... Instr was {} " , inst . value ) ;
2022-11-23 18:04:35 +01:00
}
}
} ,
2023-01-18 22:15:06 +01:00
// store instructions
2023-01-16 19:12:20 +01:00
RISCV_ST = > {
match inst . funct3 {
RISCV_ST_STB = > {
2023-01-18 15:26:44 +01:00
Self ::write_memory ( machine , 1 , ( machine . int_reg [ inst . rs1 as usize ] + inst . imm12_S_signed as i64 ) as usize , machine . int_reg [ inst . rs2 as usize ] as u64 ) ; // Possible bugs à cause du cast ici
2023-01-16 19:12:20 +01:00
} ,
RISCV_ST_STH = > {
2023-01-18 15:26:44 +01:00
Self ::write_memory ( machine , 2 , ( machine . int_reg [ inst . rs1 as usize ] + inst . imm12_S_signed as i64 ) as usize , machine . int_reg [ inst . rs2 as usize ] as u64 ) ;
2023-01-16 19:12:20 +01:00
} ,
RISCV_ST_STW = > {
2023-01-18 15:26:44 +01:00
Self ::write_memory ( machine , 4 , ( machine . int_reg [ inst . rs1 as usize ] + inst . imm12_S_signed as i64 ) as usize , machine . int_reg [ inst . rs2 as usize ] as u64 ) ;
2023-01-16 19:12:20 +01:00
} ,
RISCV_ST_STD = > {
2023-01-18 15:26:44 +01:00
Self ::write_memory ( machine , 8 , ( machine . int_reg [ inst . rs1 as usize ] + inst . imm12_S_signed as i64 ) as usize , machine . int_reg [ inst . rs2 as usize ] as u64 ) ;
2023-01-16 19:12:20 +01:00
} ,
_ = > {
panic! ( " In ST switch case, this should never happen... Instr was {} " , inst . value ) ;
}
}
}
2022-11-09 17:35:16 +01:00
//******************************************************************************************
// Treatment for: OPI INSTRUCTIONS
RISCV_OPI = > {
2022-11-15 21:21:24 +01:00
match inst . funct3 {
2022-11-09 17:35:16 +01:00
RISCV_OPI_ADDI = > {
2022-11-23 18:04:35 +01:00
machine . int_reg [ inst . rd as usize ] = machine . int_reg [ inst . rs1 as usize ] + inst . imm12_I_signed as i64 ;
2022-11-09 17:35:16 +01:00
} ,
RISCV_OPI_SLTI = > {
2023-01-11 15:34:12 +01:00
machine . int_reg [ inst . rd as usize ] = ( machine . int_reg [ inst . rs1 as usize ] < inst . imm12_I_signed as i64 ) as i64 ;
2022-11-09 17:35:16 +01:00
} ,
RISCV_OPI_XORI = > {
2022-11-23 18:04:35 +01:00
machine . int_reg [ inst . rd as usize ] = machine . int_reg [ inst . rs1 as usize ] ^ inst . imm12_I_signed as i64 ;
2022-11-09 17:35:16 +01:00
} ,
RISCV_OPI_ORI = > {
2022-11-23 18:04:35 +01:00
machine . int_reg [ inst . rd as usize ] = machine . int_reg [ inst . rs1 as usize ] | inst . imm12_I_signed as i64 ;
2022-11-09 17:35:16 +01:00
} ,
RISCV_OPI_ANDI = > {
2022-11-23 18:04:35 +01:00
machine . int_reg [ inst . rd as usize ] = machine . int_reg [ inst . rs1 as usize ] & inst . imm12_I_signed as i64 ;
2022-11-09 17:35:16 +01:00
} ,
RISCV_OPI_SLLI = > {
machine . int_reg [ inst . rd as usize ] = machine . int_reg [ inst . rs1 as usize ] < < inst . shamt ;
2022-11-16 17:59:09 +01:00
} ,
RISCV_OPI_SRI = > {
if inst . funct7_smaller = = RISCV_OPI_SRI_SRLI {
2022-11-23 18:04:35 +01:00
machine . int_reg [ inst . rd as usize ] = ( machine . int_reg [ inst . rs1 as usize ] > > inst . shamt ) & machine . shiftmask [ inst . shamt as usize ] as i64 ;
2022-11-16 17:59:09 +01:00
} else { // SRAI
2022-11-23 16:04:21 +01:00
machine . int_reg [ inst . rd as usize ] = machine . int_reg [ inst . rs1 as usize ] > > inst . shamt ;
2022-11-16 17:59:09 +01:00
}
2022-11-09 17:35:16 +01:00
}
2023-01-18 15:26:44 +01:00
_ = > { panic! ( " In OPI switch case, this should never happen... Instr was %x \n {} " , inst . value ) ; }
2022-11-09 17:35:16 +01:00
}
} ,
2022-11-15 21:21:24 +01:00
RISCV_OP = > {
2023-01-16 19:12:20 +01:00
if inst . funct7 = = 1 {
2022-11-16 17:48:55 +01:00
match inst . funct3 {
RISCV_OP_M_MUL = > {
long_result = ( machine . int_reg [ inst . rs1 as usize ] * machine . int_reg [ inst . rs2 as usize ] ) as i128 ;
2022-11-23 18:04:35 +01:00
machine . int_reg [ inst . rd as usize ] = ( long_result & 0xffffffffffffffff ) as i64 ;
2022-11-16 17:48:55 +01:00
} ,
RISCV_OP_M_MULH = > {
long_result = ( machine . int_reg [ inst . rs1 as usize ] * machine . int_reg [ inst . rs2 as usize ] ) as i128 ;
2023-01-16 19:12:20 +01:00
machine . int_reg [ inst . rd as usize ] = ( ( long_result > > 64 ) & 0xffffffffffffffff ) as i64 ;
2022-11-16 17:48:55 +01:00
} ,
RISCV_OP_M_MULHSU = > {
unsigned_reg2 = machine . int_reg [ inst . rs2 as usize ] as u64 ;
2023-01-16 19:12:20 +01:00
long_result = ( machine . int_reg [ inst . rs1 as usize ] as u64 * unsigned_reg2 ) as i128 ;
machine . int_reg [ inst . rd as usize ] = ( ( long_result > > 64 ) & 0xffffffffffffffff ) as i64 ;
2022-11-16 17:48:55 +01:00
} ,
// 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 = > {
unsigned_reg1 = machine . int_reg [ inst . rs1 as usize ] as u64 ;
unsigned_reg2 = machine . int_reg [ inst . rs2 as usize ] as u64 ;
long_result = ( unsigned_reg1 * unsigned_reg2 ) as i128 ;
2022-11-23 18:04:35 +01:00
machine . int_reg [ inst . rd as usize ] = ( ( long_result > > 64 ) & 0xffffffffffffffff ) as i64 ;
2022-11-16 17:48:55 +01:00
} ,
RISCV_OP_M_DIV = > {
2022-11-23 16:04:21 +01:00
machine . int_reg [ inst . rd as usize ] = machine . int_reg [ inst . rs1 as usize ] / machine . int_reg [ inst . rs2 as usize ] ;
2022-11-15 21:21:24 +01:00
}
2022-11-16 17:48:55 +01:00
_ = > {
2023-01-16 19:12:20 +01:00
panic! ( " RISCV_OP : funct7 = 1 (Multiplication) :: Error \n " ) ;
2022-11-16 17:48:55 +01:00
}
}
} else {
match inst . funct3 {
RISCV_OP_ADD = > {
2023-01-11 15:04:54 +01:00
if inst . funct7 = = RISCV_OP_ADD_ADD {
2022-12-07 17:09:53 +01:00
machine . int_reg [ inst . rd as usize ] = machine . int_reg [ inst . rs1 as usize ] + machine . int_reg [ inst . rs2 as usize ] ;
} else {
machine . int_reg [ inst . rd as usize ] = machine . int_reg [ inst . rs1 as usize ] - machine . int_reg [ inst . rs2 as usize ] ;
}
2022-11-16 17:48:55 +01:00
} ,
RISCV_OP_SLL = > {
machine . int_reg [ inst . rd as usize ] = machine . int_reg [ inst . rs1 as usize ] < < ( machine . int_reg [ inst . rs2 as usize ] & 0x3f ) ;
} ,
RISCV_OP_SLT = > {
if machine . int_reg [ inst . rs1 as usize ] < machine . int_reg [ inst . rs2 as usize ] {
2023-01-18 17:01:48 +01:00
machine . int_reg [ inst . rd as usize ] = 1 ;
2022-11-16 17:48:55 +01:00
} else {
2023-01-18 17:01:48 +01:00
machine . int_reg [ inst . rd as usize ] = 0 ;
2022-11-16 17:48:55 +01:00
}
} ,
RISCV_OP_SLTU = > {
unsigned_reg1 = machine . int_reg [ inst . rs1 as usize ] as u64 ;
unsigned_reg2 = machine . int_reg [ inst . rs2 as usize ] as u64 ;
if unsigned_reg1 < unsigned_reg2 {
machine . int_reg [ inst . rd as usize ] = 1 ;
} else {
machine . int_reg [ inst . rd as usize ] = 0 ;
}
} ,
RISCV_OP_XOR = > {
machine . int_reg [ inst . rd as usize ] = machine . int_reg [ inst . rs1 as usize ] ^ machine . int_reg [ inst . rs2 as usize ] ;
} ,
RISCV_OP_SR = > {
// RISCV_OP_SR_SRL inaccessible
machine . int_reg [ inst . rd as usize ] = machine . int_reg [ inst . rs1 as usize ] > > ( machine . int_reg [ inst . rs2 as usize ] & 0x3f ) ;
} ,
RISCV_OP_OR = > {
machine . int_reg [ inst . rd as usize ] = machine . int_reg [ inst . rs1 as usize ] | machine . int_reg [ inst . rs2 as usize ] ;
} ,
RISCV_OP_AND = > {
machine . int_reg [ inst . rd as usize ] = machine . int_reg [ inst . rs1 as usize ] & machine . int_reg [ inst . rs2 as usize ] ;
} ,
_ = > {
2023-01-16 19:12:20 +01:00
panic! ( " RISCV_OP undefined case \n " ) ;
2022-11-15 21:21:24 +01:00
}
2022-11-16 17:48:55 +01:00
} //LA
2022-11-15 21:21:24 +01:00
}
2022-11-16 17:59:09 +01:00
} ,
//******************************************************************************************
// Treatment for: OPW INSTRUCTIONS
RISCV_OPW = > {
if inst . funct7 = = 1 {
2023-01-11 15:04:54 +01:00
let local_data_a = machine . int_reg [ inst . rs1 as usize ] & 0xffffffff ;
let local_data_b = machine . int_reg [ inst . rs2 as usize ] & 0xffffffff ;
let local_data_a_unsigned = machine . int_reg [ inst . rs1 as usize ] & 0xffffffff ;
let local_data_b_unsigned = machine . int_reg [ inst . rs2 as usize ] & 0xffffffff ;
2022-11-16 17:59:09 +01:00
// Match case for multiplication operations (in standard extension RV32M)
match inst . funct3 {
RISCV_OPW_M_MULW = > {
2023-01-11 15:04:54 +01:00
machine . int_reg [ inst . rd as usize ] = local_data_a * local_data_b ;
2022-11-16 17:59:09 +01:00
} ,
RISCV_OPW_M_DIVW = > {
2023-01-11 15:04:54 +01:00
machine . int_reg [ inst . rd as usize ] = local_data_a / local_data_b ;
2022-11-16 17:59:09 +01:00
} ,
RISCV_OPW_M_DIVUW = > {
2023-01-11 15:04:54 +01:00
machine . int_reg [ inst . rd as usize ] = local_data_a_unsigned / local_data_b_unsigned ;
2022-11-16 17:59:09 +01:00
} ,
RISCV_OPW_M_REMW = > {
2023-01-11 15:04:54 +01:00
machine . int_reg [ inst . rd as usize ] = local_data_a % local_data_b ;
2022-11-16 17:59:09 +01:00
} ,
RISCV_OPW_M_REMUW = > {
2023-01-11 15:04:54 +01:00
machine . int_reg [ inst . rd as usize ] = local_data_a_unsigned % local_data_b_unsigned ;
2022-11-16 17:59:09 +01:00
} ,
_ = > {
2023-01-16 19:12:20 +01:00
panic! ( " this instruction ( {} ) doesn't exists " , inst . value ) ;
2022-11-16 17:59:09 +01:00
}
}
} else {
2022-11-23 16:04:21 +01:00
let local_dataa = machine . int_reg [ inst . rs1 as usize ] & 0xffffffff ;
let local_datab = machine . int_reg [ inst . rs2 as usize ] & 0xffffffff ;
2022-11-16 17:59:09 +01:00
// Match case for base OP operation
match inst . funct3 {
RISCV_OPW_ADDSUBW = > {
if inst . funct7 = = RISCV_OPW_ADDSUBW_ADDW {
2022-11-23 16:04:21 +01:00
machine . int_reg [ inst . rd as usize ] = local_dataa + local_datab ;
2022-11-16 17:59:09 +01:00
} else { // SUBW
2022-11-23 16:04:21 +01:00
machine . int_reg [ inst . rd as usize ] = local_dataa - local_datab ;
2022-11-16 17:59:09 +01:00
}
} ,
RISCV_OPW_SLLW = > {
2022-11-23 16:04:21 +01:00
machine . int_reg [ inst . rd as usize ] = local_dataa < < ( local_datab & 0x1f ) ;
2022-11-16 17:59:09 +01:00
} ,
RISCV_OPW_SRW = > {
if inst . funct7 = = RISCV_OPW_SRW_SRLW {
2022-11-23 18:04:35 +01:00
machine . int_reg [ inst . rd as usize ] = local_dataa > > ( local_datab & 0x1f ) & machine . shiftmask [ 32 + local_datab as usize ] as i64 ;
2022-11-16 17:59:09 +01:00
} else { // SRAW
2022-11-23 16:04:21 +01:00
machine . int_reg [ inst . rd as usize ] = local_dataa > > ( local_datab & 0x1f ) ;
2022-11-16 17:59:09 +01:00
}
} ,
_ = > {
2023-01-16 19:12:20 +01:00
panic! ( " this instruction ( {} ) doesn't exists " , inst . value ) ;
2022-11-16 17:59:09 +01:00
}
}
}
2022-11-16 15:48:46 +01:00
}
2023-01-16 19:12:20 +01:00
_ = > { panic! ( " {} opcode non géré " , inst . opcode ) } ,
2022-11-09 16:47:26 +01:00
}
2022-12-07 17:09:53 +01:00
machine . pc + = 4 ;
2022-11-09 16:47:26 +01:00
}
2022-11-09 15:59:05 +01:00
}
#[ cfg(test) ]
mod test {
2023-01-18 17:01:48 +01:00
use crate ::simulator ::machine ::Machine ;
2023-01-11 15:36:27 +01:00
2023-01-18 17:01:48 +01:00
#[ test ]
fn test_read_memory ( ) {
let mut m = Machine ::_init_machine ( ) ;
m . main_memory [ 4 ] = 43 ;
m . main_memory [ 5 ] = 150 ;
assert_eq! ( ( 43 < < 8 ) + 150 , Machine ::read_memory ( & mut m , 2 , 4 ) ) ;
}
2023-01-18 17:42:56 +01:00
#[ test ]
2023-01-18 17:01:48 +01:00
fn test_write_memory ( ) {
let mut m = Machine ::_init_machine ( ) ;
Machine ::write_memory ( & mut m , 2 , 6 , ( 43 < < 8 ) + 150 ) ;
assert_eq! ( 43 , m . main_memory [ 6 ] ) ;
assert_eq! ( 150 , m . main_memory [ 7 ] ) ;
}
2023-01-11 15:36:27 +01:00
}