forked from MightyPork/crsn
You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
207 lines
5.7 KiB
207 lines
5.7 KiB
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,
|
|
}
|
|
}
|
|
|
|
#[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(())
|
|
}
|
|
}
|
|
|