use crate::Imm06;
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, strum::FromRepr)]
#[cfg_attr(feature = "typescript", wasm_bindgen::prelude::wasm_bindgen(js_name = NarrowMathOp))]
#[repr(u8)]
#[must_use]
pub enum MathOp {
ADD = 0,
SUB = 1,
MUL = 2,
EXP = 3,
SLL = 4,
XNOR = 5,
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, strum::FromRepr)]
#[cfg_attr(feature = "typescript", wasm_bindgen::prelude::wasm_bindgen)]
#[repr(u8)]
#[must_use]
pub enum OpWidth {
U8 = 0,
U16 = 1,
U32 = 2,
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
#[cfg_attr(feature = "typescript", wasm_bindgen::prelude::wasm_bindgen(js_name = NarrowMathArgs))]
#[must_use]
pub struct MathArgs {
pub op: MathOp,
pub width: OpWidth,
}
impl MathArgs {
pub fn to_imm(self) -> Imm06 {
let mut bits = self.op as u8;
bits |= (self.width as u8) << 4;
Imm06(bits)
}
pub fn from_imm(bits: Imm06) -> Option<Self> {
let op = MathOp::from_repr(bits.0 & 0b_1111)?;
let width = OpWidth::from_repr((bits.0 >> 4) & 0b11)?;
Some(Self { op, width })
}
}
#[cfg(feature = "typescript")]
#[wasm_bindgen::prelude::wasm_bindgen]
impl MathArgs {
#[wasm_bindgen(constructor)]
pub fn new(op: MathOp, width: OpWidth) -> Self {
Self { op, width }
}
}
#[cfg(test)]
mod tests {
use super::*;
#[rstest::rstest]
fn encode_decode_mathop(
#[values(MathOp::ADD, MathOp::MUL, MathOp::EXP, MathOp::SLL, MathOp::XNOR)]
op: MathOp,
#[values(OpWidth::U8, OpWidth::U16, OpWidth::U32)] width: OpWidth,
) {
let orig = MathArgs { op, width };
let decoded = MathArgs::from_imm(orig.to_imm()).expect("decode error");
assert_eq!(orig, decoded);
}
#[test]
fn decode_encode_mathop() {
for imm in 0..Imm06::MAX.0 {
let bits = Imm06::from(imm);
if let Some(decoded) = MathArgs::from_imm(bits) {
assert_eq!(decoded.to_imm().0, imm);
}
}
}
}