From 60155c9a524bd3b595e51a0ff080e8d050a4cd74 Mon Sep 17 00:00:00 2001 From: lenawanel Date: Thu, 30 May 2024 00:42:36 +0200 Subject: [PATCH] add nan_boxing fixes https://github.com/d0iasm/rvemu/issues/32#issue-2318564056 --- src/cpu.rs | 121 +++++++++++++++++++++++++++++++---------------------- 1 file changed, 72 insertions(+), 49 deletions(-) diff --git a/src/cpu.rs b/src/cpu.rs index b838849..ea4a16a 100644 --- a/src/cpu.rs +++ b/src/cpu.rs @@ -2500,11 +2500,12 @@ impl Cpu { inst_count!(self, "fmadd.s"); self.debug(inst, "fmadd.s"); - self.fregs.write( + self.fregs.write_nanboxed( rd, - (self.fregs.read(rs1) as f32) - .mul_add(self.fregs.read(rs2) as f32, self.fregs.read(rs3) as f32) - as f64, + (self.fregs.read_nanboxed(rs1)).mul_add( + self.fregs.read_nanboxed(rs2) , + self.fregs.read_nanboxed(rs3) , + ), ); } 0x1 => { @@ -2535,11 +2536,12 @@ impl Cpu { inst_count!(self, "fmsub.s"); self.debug(inst, "fmsub.s"); - self.fregs.write( + self.fregs.write_nanboxed( rd, - (self.fregs.read(rs1) as f32) - .mul_add(self.fregs.read(rs2) as f32, -self.fregs.read(rs3) as f32) - as f64, + self.fregs.read_nanboxed(rs1).mul_add( + self.fregs.read_nanboxed(rs2), + -self.fregs.read_nanboxed(rs3), + ), ); } 0x1 => { @@ -2570,11 +2572,12 @@ impl Cpu { inst_count!(self, "fnmadd.s"); self.debug(inst, "fnmadd.s"); - self.fregs.write( + self.fregs.write_nanboxed( rd, - (-self.fregs.read(rs1) as f32) - .mul_add(self.fregs.read(rs2) as f32, self.fregs.read(rs3) as f32) - as f64, + (-self.fregs.read_nanboxed(rs1)).mul_add( + self.fregs.read_nanboxed(rs2), + self.fregs.read_nanboxed(rs3), + ), ); } 0x1 => { @@ -2604,11 +2607,12 @@ impl Cpu { inst_count!(self, "fnmsub.s"); self.debug(inst, "fnmsub.s"); - self.fregs.write( + self.fregs.write_nanboxed( rd, - (-self.fregs.read(rs1) as f32) - .mul_add(self.fregs.read(rs2) as f32, -self.fregs.read(rs3) as f32) - as f64, + (-self.fregs.read_nanboxed(rs1)).mul_add( + self.fregs.read_nanboxed(rs2), + -self.fregs.read_nanboxed(rs3), + ), ); } 0x1 => { @@ -2630,7 +2634,6 @@ impl Cpu { 0x53 => { // RV32F and RV64F // TODO: support the rounding mode encoding (rm). - // TODO: NaN Boxing of Narrower Values (Spec 12.2). // TODO: set exception flags. /* @@ -2662,9 +2665,9 @@ impl Cpu { inst_count!(self, "fadd.s"); self.debug(inst, "fadd.s"); - self.fregs.write( + self.fregs.write_nanboxed( rd, - (self.fregs.read(rs1) as f32 + self.fregs.read(rs2) as f32) as f64, + self.fregs.read_nanboxed(rs1) + self.fregs.read_nanboxed(rs2), ) } 0x01 => { @@ -2680,9 +2683,9 @@ impl Cpu { inst_count!(self, "fsub.s"); self.debug(inst, "fsub.s"); - self.fregs.write( + self.fregs.write_nanboxed( rd, - (self.fregs.read(rs1) as f32 - self.fregs.read(rs2) as f32) as f64, + self.fregs.read_nanboxed(rs1) - self.fregs.read_nanboxed(rs2), ) } 0x05 => { @@ -2698,9 +2701,9 @@ impl Cpu { inst_count!(self, "fmul.s"); self.debug(inst, "fmul.s"); - self.fregs.write( + self.fregs.write_nanboxed( rd, - (self.fregs.read(rs1) as f32 * self.fregs.read(rs2) as f32) as f64, + self.fregs.read_nanboxed(rs1) * self.fregs.read_nanboxed(rs2), ) } 0x09 => { @@ -2716,9 +2719,9 @@ impl Cpu { inst_count!(self, "fdiv.s"); self.debug(inst, "fdiv.s"); - self.fregs.write( + self.fregs.write_nanboxed( rd, - (self.fregs.read(rs1) as f32 / self.fregs.read(rs2) as f32) as f64, + self.fregs.read_nanboxed(rs1) / self.fregs.read_nanboxed(rs2), ) } 0x0d => { @@ -2736,17 +2739,23 @@ impl Cpu { inst_count!(self, "fsgnj.s"); self.debug(inst, "fsgnj.s"); - self.fregs - .write(rd, self.fregs.read(rs1).copysign(self.fregs.read(rs2))); + self.fregs.write_nanboxed( + rd, + self.fregs + .read_nanboxed(rs1) + .copysign(self.fregs.read_nanboxed(rs2)), + ); } 0x1 => { // fsgnjn.s inst_count!(self, "fsgnjn.s"); self.debug(inst, "fsgnjn.s"); - self.fregs.write( + self.fregs.write_nanboxed( rd, - self.fregs.read(rs1).copysign(-self.fregs.read(rs2)), + self.fregs + .read_nanboxed(rs1) + .copysign(-self.fregs.read_nanboxed(rs2)), ); } 0x2 => { @@ -2754,11 +2763,11 @@ impl Cpu { inst_count!(self, "fsgnjx.s"); self.debug(inst, "fsgnjx.s"); - let sign1 = (self.fregs.read(rs1) as f32).to_bits() & 0x80000000; - let sign2 = (self.fregs.read(rs2) as f32).to_bits() & 0x80000000; - let other = (self.fregs.read(rs1) as f32).to_bits() & 0x7fffffff; + let sign1 = self.fregs.read_nanboxed(rs1).to_bits() & 0x80000000; + let sign2 = self.fregs.read_nanboxed(rs2).to_bits() & 0x80000000; + let other = self.fregs.read_nanboxed(rs1).to_bits() & 0x7fffffff; self.fregs - .write(rd, f32::from_bits((sign1 ^ sign2) | other) as f64); + .write_nanboxed(rd, f32::from_bits((sign1 ^ sign2) | other)); } _ => { return Err(Exception::IllegalInstruction(inst)); @@ -2808,16 +2817,24 @@ impl Cpu { inst_count!(self, "fmin.s"); self.debug(inst, "fmin.s"); - self.fregs - .write(rd, self.fregs.read(rs1).min(self.fregs.read(rs2))); + self.fregs.write_nanboxed( + rd, + self.fregs + .read_nanboxed(rs1) + .min(self.fregs.read_nanboxed(rs2)), + ); } 0x1 => { // fmax.s inst_count!(self, "fmax.s"); self.debug(inst, "fmax.s"); - self.fregs - .write(rd, self.fregs.read(rs1).max(self.fregs.read(rs2))); + self.fregs.write_nanboxed( + rd, + self.fregs + .read_nanboxed(rs1) + .max(self.fregs.read_nanboxed(rs2)), + ); } _ => { return Err(Exception::IllegalInstruction(inst)); @@ -2885,7 +2902,9 @@ impl Cpu { self.xregs.write( rd, - if self.fregs.read(rs1) <= self.fregs.read(rs2) { + if self.fregs.read_nanboxed(rs1) + <= self.fregs.read_nanboxed(rs2) + { 1 } else { 0 @@ -2899,7 +2918,8 @@ impl Cpu { self.xregs.write( rd, - if self.fregs.read(rs1) < self.fregs.read(rs2) { + if self.fregs.read_nanboxed(rs1) < self.fregs.read_nanboxed(rs2) + { 1 } else { 0 @@ -2913,7 +2933,9 @@ impl Cpu { self.xregs.write( rd, - if self.fregs.read(rs1) == self.fregs.read(rs2) { + if self.fregs.read_nanboxed(rs1) + == self.fregs.read_nanboxed(rs2) + { 1 } else { 0 @@ -2983,7 +3005,7 @@ impl Cpu { self.xregs.write( rd, - ((self.fregs.read(rs1) as f32).round() as i32) as u64, + (self.fregs.read_nanboxed(rs1).round() as i32) as u64, ); } 0x1 => { @@ -2993,7 +3015,7 @@ impl Cpu { self.xregs.write( rd, - (((self.fregs.read(rs1) as f32).round() as u32) as i32) as u64, + ((self.fregs.read_nanboxed(rs1).round() as u32) as i32) as u64, ); } 0x2 => { @@ -3002,7 +3024,7 @@ impl Cpu { self.debug(inst, "fcvt.l.s"); self.xregs - .write(rd, (self.fregs.read(rs1) as f32).round() as u64); + .write(rd, self.fregs.read_nanboxed(rs1).round() as u64); } 0x3 => { // fcvt.lu.s @@ -3010,7 +3032,7 @@ impl Cpu { self.debug(inst, "fcvt.lu.s"); self.xregs - .write(rd, (self.fregs.read(rs1) as f32).round() as u64); + .write(rd, self.fregs.read_nanboxed(rs1).round() as u64); } _ => { return Err(Exception::IllegalInstruction(inst)); @@ -3064,7 +3086,7 @@ impl Cpu { self.debug(inst, "fcvt.s.w"); self.fregs - .write(rd, ((self.xregs.read(rs1) as i32) as f32) as f64); + .write_nanboxed(rd, (self.xregs.read(rs1) as i32) as f32); } 0x1 => { // fcvt.s.wu @@ -3072,14 +3094,15 @@ impl Cpu { self.debug(inst, "fcvt.s.wu"); self.fregs - .write(rd, ((self.xregs.read(rs1) as u32) as f32) as f64); + .write_nanboxed(rd, (self.xregs.read(rs1) as u32) as f32); } 0x2 => { // fcvt.s.l inst_count!(self, "fcvt.s.l"); self.debug(inst, "fcvt.s.l"); - self.fregs.write(rd, (self.xregs.read(rs1) as f32) as f64); + self.fregs + .write_nanboxed(rd, self.xregs.read(rs1) as i64 as f32); } 0x3 => { // fcvt.s.lu @@ -3087,7 +3110,7 @@ impl Cpu { self.debug(inst, "fcvt.s.lu"); self.fregs - .write(rd, ((self.xregs.read(rs1) as u64) as f32) as f64); + .write_nanboxed(rd, (self.xregs.read(rs1) as u64) as f32); } _ => { return Err(Exception::IllegalInstruction(inst)); @@ -3147,7 +3170,7 @@ impl Cpu { inst_count!(self, "fclass.s"); self.debug(inst, "fclass.s"); - let f = self.fregs.read(rs1); + let f = self.fregs.read_nanboxed(rs1); match f.classify() { FpCategory::Infinite => { self.xregs