summaryrefslogtreecommitdiff
path: root/src/core.rs
diff options
context:
space:
mode:
Diffstat (limited to 'src/core.rs')
-rw-r--r--src/core.rs173
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
+ }
+ }
+ }
+}