From a6af244080d05a7cac31e419a2b8058325c8c99b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Emil=20Gardstr=C3=B6m?= Date: Mon, 29 Apr 2024 13:23:28 +0200 Subject: [PATCH 1/2] use more correct logic for `mod` --- ic10emu/src/interpreter.rs | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/ic10emu/src/interpreter.rs b/ic10emu/src/interpreter.rs index d3bd663..76006c6 100644 --- a/ic10emu/src/interpreter.rs +++ b/ic10emu/src/interpreter.rs @@ -1745,7 +1745,11 @@ impl IC { } = reg.as_register(this, inst, 1)?; let a = a.as_value(this, inst, 2)?; let b = b.as_value(this, inst, 1)?; - this.set_register(indirection, target, ((a % b) + b) % b)?; + let mut m = (a % b); + if m < 0.0 { + m += b; + } + this.set_register(indirection, target, m)?; Ok(()) } oprs => Err(ICError::mismatch_operands(oprs.len(), 3)), From ed8cdb575c19cf9c042b4c60cd8c73b1859ab3fe Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Emil=20Gardstr=C3=B6m?= Date: Mon, 29 Apr 2024 17:30:01 +0200 Subject: [PATCH 2/2] fix bitwise operations --- ic10emu/src/grammar.rs | 11 +++++----- ic10emu/src/interpreter.rs | 43 +++++++++++++++++++++----------------- 2 files changed, 29 insertions(+), 25 deletions(-) diff --git a/ic10emu/src/grammar.rs b/ic10emu/src/grammar.rs index 3e6f4a1..027dc14 100644 --- a/ic10emu/src/grammar.rs +++ b/ic10emu/src/grammar.rs @@ -432,7 +432,7 @@ impl Operand { index: u32, ) -> Result { match self { - Self::Number(num) => Ok(num.value_i64()), + Self::Number(num) => Ok(num.value_i64(signed)), _ => { let val = self.as_value(ic, inst, index)?; if val < -9.223_372_036_854_776E18 { @@ -445,15 +445,15 @@ impl Operand { } } } - pub fn as_value_i32( &self, ic: &interpreter::IC, + signed: bool, inst: InstructionOp, index: u32, ) -> Result { match self { - Self::Number(num) => Ok(num.value_i64() as i32), + Self::Number(num) => Ok(num.value_i64(signed) as i32), _ => { let val = self.as_value(ic, inst, index)?; if val < -2147483648.0 { @@ -1079,9 +1079,9 @@ impl Number { Number::String(s) => const_crc32::crc32(s.as_bytes()) as i32 as f64, } } - pub fn value_i64(&self) -> i64 { + pub fn value_i64(&self, signed: bool) -> i64 { match self { - Number::Enum(val) | Number::Float(val) | Number::Constant(val) => *val as i64, + Number::Enum(val) | Number::Float(val) | Number::Constant(val) => interpreter::f64_to_i64(*val, signed), Number::Binary(val) | Number::Hexadecimal(val) => *val, Number::String(s) => const_crc32::crc32(s.as_bytes()) as i32 as i64, } @@ -1471,7 +1471,6 @@ mod tests { test_roundtrip("%1001"); } - #[test] fn all_generated_enums_have_value() { use strum::IntoEnumIterator; diff --git a/ic10emu/src/interpreter.rs b/ic10emu/src/interpreter.rs index 76006c6..1094b51 100644 --- a/ic10emu/src/interpreter.rs +++ b/ic10emu/src/interpreter.rs @@ -1,6 +1,10 @@ use core::f64; use serde::{Deserialize, Serialize}; -use std::{cell::{Cell, RefCell}, ops::Deref, string::ToString}; +use std::{ + cell::{Cell, RefCell}, + ops::Deref, + string::ToString, +}; use std::{ collections::{BTreeMap, HashSet}, error::Error, @@ -13,7 +17,9 @@ use itertools::Itertools; use time::format_description; use crate::{ - device::SlotType, grammar::{self, LogicType, ParseError, SlotLogicType}, vm::VM + device::SlotType, + grammar::{self, LogicType, ParseError, SlotLogicType}, + vm::VM, }; use serde_with::serde_as; @@ -434,12 +440,7 @@ impl IC { } /// sets a register thorough, recursing through provided indirection, returns value previously - pub fn set_register( - &self, - indirection: u32, - target: u32, - val: f64, - ) -> Result { + pub fn set_register(&self, indirection: u32, target: u32, val: f64) -> Result { let t = self.get_real_target(indirection, target)?; let mut registers = self.registers.borrow_mut(); let old_val = registers @@ -525,7 +526,11 @@ impl IC { if let Some(device) = vm.devices.get(&self.device) { let mut device_ref = device.borrow_mut(); let _ = device_ref.set_field(LogicType::LineNumber, self.ip.get() as f64, vm, true); - if let Some(slot) = device_ref.slots.iter_mut().find(|slot| slot.typ == SlotType::ProgrammableChip) { + if let Some(slot) = device_ref + .slots + .iter_mut() + .find(|slot| slot.typ == SlotType::ProgrammableChip) + { let _ = slot.set_field(SlotLogicType::LineNumber, self.ip.get() as f64, true); } } @@ -1745,7 +1750,7 @@ impl IC { } = reg.as_register(this, inst, 1)?; let a = a.as_value(this, inst, 2)?; let b = b.as_value(this, inst, 1)?; - let mut m = (a % b); + let mut m = a % b; if m < 0.0 { m += b; } @@ -1984,7 +1989,7 @@ impl IC { target, } = reg.as_register(this, inst, 1)?; let a = a.as_value_i64(this, true, inst, 2)?; - let b = b.as_value_i32(this, inst, 3)?; + let b = b.as_value_i32(this, true, inst, 3)?; this.set_register(indirection, target, i64_to_f64(a << b))?; Ok(()) } @@ -1997,7 +2002,7 @@ impl IC { target, } = reg.as_register(this, inst, 1)?; let a = a.as_value_i64(this, false, inst, 2)?; - let b = b.as_value_i32(this, inst, 3)?; + let b = b.as_value_i32(this, true, inst, 3)?; this.set_register(indirection, target, i64_to_f64((a as u64 >> b) as i64))?; Ok(()) } @@ -2010,7 +2015,7 @@ impl IC { target, } = reg.as_register(this, inst, 1)?; let a = a.as_value_i64(this, true, inst, 2)?; - let b = b.as_value_i32(this, inst, 3)?; + let b = b.as_value_i32(this, true, inst, 3)?; this.set_register(indirection, target, i64_to_f64(a >> b))?; Ok(()) } @@ -2603,18 +2608,18 @@ impl LogicTypeExt for grammar::LogicType { } pub fn f64_to_i64(f: f64, signed: bool) -> i64 { - let mut num: i64 = (f % 9007199254740992.0) as i64; + let mut num: i64 = (f % (1i64 << 53) as f64) as i64; if !signed { - num &= 18014398509481983_i64; + num &= (1i64 << 54) - 1; } num } - pub fn i64_to_f64(i: i64) -> f64 { - let flag: bool = (i & 9007199254740992_i64) != 0; - let mut i = i & 9007199254740991_i64; + const MASK: i64 = 1 << 53; + let flag: bool = (i & MASK) != 0; + let mut i = i & (MASK - 1); if flag { - i &= -9007199254740992_i64; + i |= -MASK; } i as f64 }