Croissant Runtime
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.
 
 
crsn/crsn/src/runtime/frame/status.rs

190 lines
5.3 KiB

use std::fmt::{Display, Formatter};
use std::fmt;
use crate::asm::data::literal::{is_negative, is_positive, Value};
use crate::asm::instr::Cond;
#[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,
}
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; }
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; }
}
#[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 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,
}
}
#[inline(always)]
pub fn set(&mut self, cond: Cond) {
match cond {
Cond::Equal => {
self.equal = true;
}
Cond::Zero => {
self.zero = true;
}
Cond::Lower => {
self.lower = true;
}
Cond::Greater => {
self.lower = false;
self.equal = false;
self.greater = true;
}
Cond::Positive => {
self.positive = true;
}
Cond::Negative => {
self.negative = true;
}
Cond::Overflow => {
self.overflow = true;
}
Cond::Invalid => {
self.invalid = true;
}
Cond::Carry => {
self.carry = true;
}
Cond::Empty => {
self.empty = true;
}
Cond::Full => {
self.full = true;
}
other => {
error!("Cannot set cond by {:?}", other);
// ...and do nothing. Don't panic, we don't want to crash the runtime!
}
}
}
}
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")?;
}
f.write_str(" ]")?;
Ok(())
}
}