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/asm/instr/cond.rs

152 lines
4.1 KiB

use std::fmt::{self, Display, Formatter};
use std::ops::Not;
use sexp::SourcePosition;
use crate::asm::error::CrsnError;
/// Condition flag
#[derive(Clone, Copy, Debug, Eq, PartialEq, Hash)]
pub enum Cond {
/// Equality
Equal,
/// Inequality
NotEqual,
/// Equal to zero
Zero,
/// Not equal zero
NotZero,
/// A < B
Lower,
/// A <= B
LowerOrEqual,
/// A > B
Greater,
/// A >= B
GreaterOrEqual,
/// A > 0
Positive,
/// A <= 0
NonPositive,
/// A < 0
Negative,
/// A >= 0
NonNegative,
/// Arithmetic operation caused an integer operand to overflow
Overflow,
/// No overflow
NotOverflow,
/// Arithmetic (or other) operation was invalid.
/// Example: division by zero
Invalid,
/// Operation was valid
Valid,
/// Arithmetic carry
Carry,
/// Carry not set
NotCarry,
// Full
Full,
/// Not full
NotFull,
// Empty
Empty,
/// Not empty
NotEmpty,
}
pub fn parse_cond(text: &str, pos: &SourcePosition) -> Result<Cond, CrsnError> {
Ok(match text.trim_end_matches('?') {
"eq" | "=" | "==" => Cond::Equal,
"ne" | "<>" | "!=" | "≠" => Cond::NotEqual,
"z" | "0" => Cond::Zero,
"nz" | "<>0" | "!0" => Cond::NotZero,
"lt" | "<" => Cond::Lower,
"le" | "<=" | "≤" => Cond::LowerOrEqual,
"gt" | ">" => Cond::Greater,
"ge" | ">=" | "≥" => Cond::GreaterOrEqual,
"pos" | "+" | ">0" => Cond::Positive,
"neg" | "-" | "<0" => Cond::Negative,
"npos" | "0-" | "<=0" | "≥0" => Cond::NonPositive,
"nneg" | "0+" | ">=0" | "≤0" => Cond::NonNegative,
"c" => Cond::Carry,
"nc" => Cond::NotCarry,
"em" => Cond::Empty,
"nem" => Cond::NotEmpty,
"f" => Cond::Full,
"nf" => Cond::NotFull,
"valid" => Cond::Valid,
"inval" => Cond::Invalid,
"ov" => Cond::Overflow,
"nov" => Cond::NotOverflow,
_ => {
return Err(CrsnError::Parse(format!("Unknown cond: {}", text).into(), pos.clone()));
}
})
}
impl Display for Cond {
fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
f.write_str(match self {
Cond::Equal => "eq",
Cond::NotEqual => "ne",
Cond::Zero => "z",
Cond::NotZero => "nz",
Cond::Empty => "emp",
Cond::NotEmpty => "nemp",
Cond::Full => "full",
Cond::NotFull => "nfull",
Cond::Lower => "lt",
Cond::LowerOrEqual => "le",
Cond::Greater => "gt",
Cond::GreaterOrEqual => "ge",
Cond::Positive => "pos",
Cond::Negative => "neg",
Cond::NonPositive => "npos",
Cond::NonNegative => "nneg",
Cond::Overflow => "ov",
Cond::NotOverflow => "nov",
Cond::Carry => "c",
Cond::NotCarry => "nc",
Cond::Invalid => "inval",
Cond::Valid => "valid",
})
}
}
impl Not for Cond {
type Output = Cond;
fn not(self) -> Self::Output {
match self {
Cond::Equal => Cond::NotEqual,
Cond::Zero => Cond::NotZero,
Cond::Overflow => Cond::NotOverflow,
Cond::Carry => Cond::NotCarry,
Cond::Empty => Cond::NotEmpty,
Cond::NotEmpty => Cond::Empty,
Cond::Full => Cond::NotFull,
Cond::NotFull => Cond::Full,
Cond::Positive => Cond::NonPositive,
Cond::Negative => Cond::NonNegative,
Cond::NonPositive => Cond::Positive,
Cond::NonNegative => Cond::Negative,
Cond::NotEqual => Cond::Equal,
Cond::NotZero => Cond::Zero,
Cond::NotOverflow => Cond::Overflow,
Cond::NotCarry => Cond::Carry,
Cond::Lower => Cond::GreaterOrEqual,
Cond::Greater => Cond::LowerOrEqual,
Cond::LowerOrEqual => Cond::Greater,
Cond::GreaterOrEqual => Cond::Lower,
Cond::Invalid => Cond::Valid,
Cond::Valid => Cond::Invalid,
}
}
}