fix bitwise operations
This commit is contained in:
@@ -432,7 +432,7 @@ impl Operand {
|
|||||||
index: u32,
|
index: u32,
|
||||||
) -> Result<i64, interpreter::ICError> {
|
) -> Result<i64, interpreter::ICError> {
|
||||||
match self {
|
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)?;
|
let val = self.as_value(ic, inst, index)?;
|
||||||
if val < -9.223_372_036_854_776E18 {
|
if val < -9.223_372_036_854_776E18 {
|
||||||
@@ -445,15 +445,15 @@ impl Operand {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn as_value_i32(
|
pub fn as_value_i32(
|
||||||
&self,
|
&self,
|
||||||
ic: &interpreter::IC,
|
ic: &interpreter::IC,
|
||||||
|
signed: bool,
|
||||||
inst: InstructionOp,
|
inst: InstructionOp,
|
||||||
index: u32,
|
index: u32,
|
||||||
) -> Result<i32, interpreter::ICError> {
|
) -> Result<i32, interpreter::ICError> {
|
||||||
match self {
|
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)?;
|
let val = self.as_value(ic, inst, index)?;
|
||||||
if val < -2147483648.0 {
|
if val < -2147483648.0 {
|
||||||
@@ -1079,9 +1079,9 @@ impl Number {
|
|||||||
Number::String(s) => const_crc32::crc32(s.as_bytes()) as i32 as f64,
|
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 {
|
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::Binary(val) | Number::Hexadecimal(val) => *val,
|
||||||
Number::String(s) => const_crc32::crc32(s.as_bytes()) as i32 as i64,
|
Number::String(s) => const_crc32::crc32(s.as_bytes()) as i32 as i64,
|
||||||
}
|
}
|
||||||
@@ -1471,7 +1471,6 @@ mod tests {
|
|||||||
test_roundtrip("%1001");
|
test_roundtrip("%1001");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn all_generated_enums_have_value() {
|
fn all_generated_enums_have_value() {
|
||||||
use strum::IntoEnumIterator;
|
use strum::IntoEnumIterator;
|
||||||
|
|||||||
@@ -1,6 +1,10 @@
|
|||||||
use core::f64;
|
use core::f64;
|
||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
use std::{cell::{Cell, RefCell}, ops::Deref, string::ToString};
|
use std::{
|
||||||
|
cell::{Cell, RefCell},
|
||||||
|
ops::Deref,
|
||||||
|
string::ToString,
|
||||||
|
};
|
||||||
use std::{
|
use std::{
|
||||||
collections::{BTreeMap, HashSet},
|
collections::{BTreeMap, HashSet},
|
||||||
error::Error,
|
error::Error,
|
||||||
@@ -13,7 +17,9 @@ use itertools::Itertools;
|
|||||||
use time::format_description;
|
use time::format_description;
|
||||||
|
|
||||||
use crate::{
|
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;
|
use serde_with::serde_as;
|
||||||
@@ -434,12 +440,7 @@ impl IC {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// sets a register thorough, recursing through provided indirection, returns value previously
|
/// sets a register thorough, recursing through provided indirection, returns value previously
|
||||||
pub fn set_register(
|
pub fn set_register(&self, indirection: u32, target: u32, val: f64) -> Result<f64, ICError> {
|
||||||
&self,
|
|
||||||
indirection: u32,
|
|
||||||
target: u32,
|
|
||||||
val: f64,
|
|
||||||
) -> Result<f64, ICError> {
|
|
||||||
let t = self.get_real_target(indirection, target)?;
|
let t = self.get_real_target(indirection, target)?;
|
||||||
let mut registers = self.registers.borrow_mut();
|
let mut registers = self.registers.borrow_mut();
|
||||||
let old_val = registers
|
let old_val = registers
|
||||||
@@ -525,7 +526,11 @@ impl IC {
|
|||||||
if let Some(device) = vm.devices.get(&self.device) {
|
if let Some(device) = vm.devices.get(&self.device) {
|
||||||
let mut device_ref = device.borrow_mut();
|
let mut device_ref = device.borrow_mut();
|
||||||
let _ = device_ref.set_field(LogicType::LineNumber, self.ip.get() as f64, vm, true);
|
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);
|
let _ = slot.set_field(SlotLogicType::LineNumber, self.ip.get() as f64, true);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1745,7 +1750,7 @@ impl IC {
|
|||||||
} = reg.as_register(this, inst, 1)?;
|
} = reg.as_register(this, inst, 1)?;
|
||||||
let a = a.as_value(this, inst, 2)?;
|
let a = a.as_value(this, inst, 2)?;
|
||||||
let b = b.as_value(this, inst, 1)?;
|
let b = b.as_value(this, inst, 1)?;
|
||||||
let mut m = (a % b);
|
let mut m = a % b;
|
||||||
if m < 0.0 {
|
if m < 0.0 {
|
||||||
m += b;
|
m += b;
|
||||||
}
|
}
|
||||||
@@ -1984,7 +1989,7 @@ impl IC {
|
|||||||
target,
|
target,
|
||||||
} = reg.as_register(this, inst, 1)?;
|
} = reg.as_register(this, inst, 1)?;
|
||||||
let a = a.as_value_i64(this, true, inst, 2)?;
|
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))?;
|
this.set_register(indirection, target, i64_to_f64(a << b))?;
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
@@ -1997,7 +2002,7 @@ impl IC {
|
|||||||
target,
|
target,
|
||||||
} = reg.as_register(this, inst, 1)?;
|
} = reg.as_register(this, inst, 1)?;
|
||||||
let a = a.as_value_i64(this, false, inst, 2)?;
|
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))?;
|
this.set_register(indirection, target, i64_to_f64((a as u64 >> b) as i64))?;
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
@@ -2010,7 +2015,7 @@ impl IC {
|
|||||||
target,
|
target,
|
||||||
} = reg.as_register(this, inst, 1)?;
|
} = reg.as_register(this, inst, 1)?;
|
||||||
let a = a.as_value_i64(this, true, inst, 2)?;
|
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))?;
|
this.set_register(indirection, target, i64_to_f64(a >> b))?;
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
@@ -2603,18 +2608,18 @@ impl LogicTypeExt for grammar::LogicType {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub fn f64_to_i64(f: f64, signed: bool) -> i64 {
|
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 {
|
if !signed {
|
||||||
num &= 18014398509481983_i64;
|
num &= (1i64 << 54) - 1;
|
||||||
}
|
}
|
||||||
num
|
num
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn i64_to_f64(i: i64) -> f64 {
|
pub fn i64_to_f64(i: i64) -> f64 {
|
||||||
let flag: bool = (i & 9007199254740992_i64) != 0;
|
const MASK: i64 = 1 << 53;
|
||||||
let mut i = i & 9007199254740991_i64;
|
let flag: bool = (i & MASK) != 0;
|
||||||
|
let mut i = i & (MASK - 1);
|
||||||
if flag {
|
if flag {
|
||||||
i &= -9007199254740992_i64;
|
i |= -MASK;
|
||||||
}
|
}
|
||||||
i as f64
|
i as f64
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user