use std::fmt::{Display, Formatter}; use std::fmt; use crate::asm::data::literal::{is_negative, is_positive, Value}; use crate::asm::instr::Cond; use crate::asm::instr::cond::Flag; use num_traits::Zero; #[derive(Default, Clone, Debug)] pub struct StatusFlags { /// Arguments are equal pub equal: bool, /// A < B pub lower: bool, /// A > B pub greater: bool, /// Register is zero pub zero: bool, /// Register is positive pub positive: bool, /// Register is negative pub negative: bool, /// Overflow (multiplication etc.) pub overflow: bool, /// Invalid flag pub invalid: bool, /// Arithmetic carry pub carry: bool, /// Buffer full pub full: bool, /// Buffer empty pub empty: bool, /// Stream ended pub eof: bool, } impl StatusFlags { #[inline(always)] pub fn clear(&mut self) { *self = Self::default(); } pub fn store(&self) -> Value { let mut val = 0u64; if self.equal { val |= 0x01; } if self.lower { val |= 0x02; } if self.greater { val |= 0x04; } if self.zero { val |= 0x08; } if self.positive { val |= 0x10; } if self.negative { val |= 0x20; } if self.overflow { val |= 0x40; } if self.invalid { val |= 0x80; } if self.carry { val |= 0x100; } if self.full { val |= 0x200; } if self.empty { val |= 0x400; } if self.eof { val |= 0x800; } val } pub fn load(&mut self, val: Value) { if val & 0x01 != 0 { self.equal = true; } if val & 0x02 != 0 { self.lower = true; } if val & 0x04 != 0 { self.greater = true; } if val & 0x08 != 0 { self.zero = true; } if val & 0x10 != 0 { self.positive = true; } if val & 0x20 != 0 { self.negative = true; } if val & 0x40 != 0 { self.overflow = true; } if val & 0x80 != 0 { self.invalid = true; } if val & 0x100 != 0 { self.carry = true; } if val & 0x200 != 0 { self.full = true; } if val & 0x400 != 0 { self.empty = true; } if val & 0x800 != 0 { self.eof = true; } } #[inline(always)] pub fn update(&mut self, val: Value) { self.zero = val == 0; self.positive = is_positive(val); self.negative = is_negative(val); } #[inline(always)] pub fn update_float(&mut self, val: f64) { self.invalid = val.is_nan(); self.overflow = val.is_infinite(); self.zero = val.is_zero(); self.positive = val.is_sign_positive(); self.negative = val.is_sign_negative(); } #[inline(always)] pub fn test(&self, cond: Cond) -> bool { match cond { Cond::Equal => self.equal, Cond::NotEqual => !self.equal, Cond::Zero => self.zero, Cond::NotZero => !self.zero, Cond::Lower => self.lower, Cond::LowerOrEqual => self.lower || self.equal, Cond::Greater => self.greater, Cond::GreaterOrEqual => self.greater || self.equal, Cond::Positive => self.positive, Cond::NonPositive => !self.positive, Cond::Negative => self.negative, Cond::NonNegative => !self.negative, Cond::Overflow => self.overflow, Cond::NotOverflow => !self.overflow, Cond::Invalid => self.invalid, Cond::Valid => !self.invalid, Cond::Carry => self.carry, Cond::NotCarry => !self.carry, Cond::Full => self.full, Cond::NotFull => !self.full, Cond::Empty => self.empty, Cond::NotEmpty => !self.empty, Cond::Eof => self.eof, Cond::NotEof => !self.eof, Cond::True => true, Cond::False => false, } } #[inline(always)] pub fn set(&mut self, cond: Flag, val : bool) { match cond { Flag::Equal => { self.equal = val; } Flag::Zero => { self.zero = val; } Flag::Lower => { self.lower = val; } Flag::Greater => { self.greater = val; } Flag::Positive => { self.positive = val; } Flag::Negative => { self.negative = val; } Flag::Overflow => { self.overflow = val; } Flag::Invalid => { self.invalid = val; } Flag::Carry => { self.carry = val; } Flag::Empty => { self.empty = val; } Flag::Full => { self.full = val; } Flag::Eof => { self.eof = val; } } } } impl Display for StatusFlags { fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result { f.write_str("[")?; if self.equal { f.write_str(" =")?; } if self.zero { f.write_str(" 0")?; } if self.lower { f.write_str(" Lt")?; } if self.greater { f.write_str(" Gt")?; } if self.positive { f.write_str(" +")?; } if self.negative { f.write_str(" -")?; } if self.overflow { f.write_str(" Ov")?; } if self.invalid { f.write_str(" Inv")?; } if self.carry { f.write_str(" C")?; } if self.full { f.write_str(" Full")?; } if self.empty { f.write_str(" Emp")?; } if self.eof { f.write_str(" Eof")?; } f.write_str(" ]")?; Ok(()) } }