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.
128 lines
3.6 KiB
128 lines
3.6 KiB
use std::fmt::{self, Display, Formatter};
|
|
use std::ops::Not;
|
|
|
|
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,
|
|
}
|
|
|
|
pub fn parse_cond(text: &str) -> 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" | "!c" => Cond::NotCarry,
|
|
"valid" => Cond::Valid,
|
|
"inval" => Cond::Invalid,
|
|
"ov" | "^" => Cond::Overflow,
|
|
"nov" | "!ov" | "!^" => Cond::NotOverflow,
|
|
_ => {
|
|
return Err(CrsnError::Parse(format!("Unknown cond: {}", text).into()));
|
|
}
|
|
})
|
|
}
|
|
|
|
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::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::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,
|
|
}
|
|
}
|
|
}
|
|
|