diff options
Diffstat (limited to 'src/core.rs')
| -rw-r--r-- | src/core.rs | 173 |
1 files changed, 173 insertions, 0 deletions
diff --git a/src/core.rs b/src/core.rs index ff6bb52..251336e 100644 --- a/src/core.rs +++ b/src/core.rs @@ -1,3 +1,5 @@ +use std::num::FpCategory; + pub fn add(registers: &mut [u32; 32], rd: usize, rs1: usize, rs2: usize) { registers[rd] = registers[rs1].wrapping_add(registers[rs2]); } @@ -243,3 +245,174 @@ pub fn lui(registers: &mut [u32; 32], rd: usize, imm: u32) { pub fn auipc(registers: &mut [u32; 32], pc: u32, rd: usize, imm: u32) { registers[rd] = pc + (imm << 12); } + +pub fn fmadd_s(registers: &mut [f32; 32], rd: usize, rs1: usize, rs2: usize, rs3: usize) { + registers[rd] = registers[rs1] * registers[rs2] + registers[rs3]; +} + +pub fn fmsub_s(registers: &mut [f32; 32], rd: usize, rs1: usize, rs2: usize, rs3: usize) { + registers[rd] = registers[rs1] * registers[rs2] - registers[rs3]; +} + +pub fn fnmadd_s(registers: &mut [f32; 32], rd: usize, rs1: usize, rs2: usize, rs3: usize) { + registers[rd] = -registers[rs1] * registers[rs2] + registers[rs3]; +} + +pub fn fnmsub_s(registers: &mut [f32; 32], rd: usize, rs1: usize, rs2: usize, rs3: usize) { + registers[rd] = -registers[rs1] * registers[rs2] - registers[rs3]; +} + +pub fn fadd_s(registers: &mut [f32; 32], rd: usize, rs1: usize, rs2: usize) { + registers[rd] = registers[rs1] + registers[rs2]; +} + +pub fn fsub_s(registers: &mut [f32; 32], rd: usize, rs1: usize, rs2: usize) { + registers[rd] = registers[rs1] - registers[rs2]; +} + +pub fn fmul_s(registers: &mut [f32; 32], rd: usize, rs1: usize, rs2: usize) { + registers[rd] = registers[rs1] * registers[rs2]; +} + +pub fn fdiv_s(registers: &mut [f32; 32], rd: usize, rs1: usize, rs2: usize) { + let a = registers[rs1]; + let b = registers[rs2]; + + registers[rd] = if b == 0.0 { + f32::NAN + // todo: raise division by zero in csr + } else { + a / b + } +} + +pub fn fsqrt_s(registers: &mut [f32; 32], rd: usize, rs1: usize) { + registers[rd] = registers[rs1].sqrt(); +} + +pub fn fsgnj_s(registers: &mut [f32; 32], rd: usize, rs1: usize, rs2: usize) { + registers[rd] = registers[rs1].abs() * registers[rs2].signum(); +} +pub fn fsgnjn_s(registers: &mut [f32; 32], rd: usize, rs1: usize, rs2: usize) { + registers[rd] = registers[rs1].abs() * -registers[rs2].signum(); +} + +pub fn fsgnjx_s(registers: &mut [f32; 32], rd: usize, rs1: usize, rs2: usize) { + registers[rd] = registers[rs1] * registers[rs2].signum(); +} +pub fn fmin_s(registers: &mut [f32; 32], rd: usize, rs1: usize, rs2: usize) { + registers[rd] = registers[rs1].min(registers[rs2]); +} +pub fn fmax_s(registers: &mut [f32; 32], rd: usize, rs1: usize, rs2: usize) { + registers[rd] = registers[rs1].max(registers[rs2]); +} + +pub fn fcvt_s_w(registers: &mut [u32; 32], f_registers: &mut [f32; 32], rd: usize, rs1: usize) { + f_registers[rd] = registers[rs1] as i32 as f32; +} + +pub fn fcvt_s_wu(registers: &mut [u32; 32], f_registers: &mut [f32; 32], rd: usize, rs1: usize) { + f_registers[rd] = registers[rs1] as f32; +} + +pub fn fcvt_w_s(registers: &mut [u32; 32], f_registers: &mut [f32; 32], rd: usize, rs1: usize) { + registers[rd] = f_registers[rs1] as i32 as u32; +} + +pub fn fcvt_wu_s(registers: &mut [u32; 32], f_registers: &mut [f32; 32], rd: usize, rs1: usize) { + registers[rd] = f_registers[rs1] as u32; +} + +pub fn fmv_x_w(registers: &mut [u32; 32], f_registers: &mut [f32; 32], rd: usize, rs1: usize) { + registers[rd] = u32::from_le_bytes(f_registers[rs1].to_le_bytes()); +} + +pub fn fmv_w_x(registers: &mut [u32; 32], f_registers: &mut [f32; 32], rd: usize, rs1: usize) { + f_registers[rd] = f32::from_le_bytes(registers[rs1].to_le_bytes()); +} + +pub fn feq_s( + registers: &mut [u32; 32], + f_registers: &mut [f32; 32], + rd: usize, + rs1: usize, + rs2: usize, +) { + registers[rd] = if f_registers[rs1] == f_registers[rs2] { + 1 + } else { + 0 + } +} + +pub fn flt_s( + registers: &mut [u32; 32], + f_registers: &mut [f32; 32], + rd: usize, + rs1: usize, + rs2: usize, +) { + registers[rd] = if f_registers[rs1] < f_registers[rs2] { + 1 + } else { + 0 + } +} + +pub fn fle_s( + registers: &mut [u32; 32], + f_registers: &mut [f32; 32], + rd: usize, + rs1: usize, + rs2: usize, +) { + registers[rd] = if f_registers[rs1] <= f_registers[rs2] { + 1 + } else { + 0 + } +} + +pub fn fclass_s(registers: &mut [u32; 32], f_registers: &mut [f32; 32], rd: usize, rs1: usize) { + let number = f_registers[rs1]; + let class = number.classify(); + let frac_msb = (number.to_bits() >> 22) & 0x01; + + registers[rd] = match class { + FpCategory::Nan => { + if frac_msb == 0 { + 0b1 + } else { + 0b10 + } + } + FpCategory::Infinite => { + if number.is_sign_negative() { + 0b100 + } else { + 0b100000000 + } + } + FpCategory::Zero => { + if number.is_sign_negative() { + 0b10000 + } else { + 0b100000 + } + } + FpCategory::Subnormal => { + if number.is_sign_negative() { + 0b1000 + } else { + 0b1000000 + } + } + FpCategory::Normal => { + if number.is_sign_negative() { + 0b100 + } else { + 0b10000000 + } + } + } +} |
