use std::collections::HashMap;
use osiris_process::compare::Compare;
use osiris_process::operation::error::{OperationError, OperationResult};
use osiris_process::operation::{Operation, OperationSet};
use osiris_process::operation::scheme::{ArgumentType, InstructionScheme, OperationId};
use osiris_process::processor::Cpu;
use osiris_process::register::{RegisterBank, RegisterId};
use crate::range_applications::unsigned;
pub const SET_MASK: u16 = 0x1000;
pub const SUM_UNSIGNED: OperationId = OperationId::new(SET_MASK | 0x01);
pub const PRODUCT_UNSIGNED: OperationId = OperationId::new(SET_MASK | 0x02);
pub const DIFFERENCE_UNSIGNED: OperationId = OperationId::new(SET_MASK | 0x03);
pub const QUOTIENT_UNSIGNED: OperationId = OperationId::new(SET_MASK | 0x04);
pub const COMPARE_UNSIGNED: OperationId = OperationId::new(SET_MASK | 0x0F);
pub fn sum_unsigned(cpu: &mut Cpu, scheme: InstructionScheme) -> OperationResult<()> {
cpu.bank_apply(scheme.target, scheme.argument.get_range()?, unsigned::sum);
Ok(())
}
pub fn product_unsigned(cpu: &mut Cpu, scheme: InstructionScheme) -> OperationResult<()> {
cpu.bank_apply(scheme.target, scheme.argument.get_range()?, unsigned::product);
Ok(())
}
pub fn difference_unsigned(cpu: &mut Cpu, scheme: InstructionScheme) -> OperationResult<()> {
cpu.bank_apply(scheme.target, scheme.argument.get_range()?, unsigned::difference);
Ok(())
}
pub fn quotient_unsigned(cpu: &mut Cpu, scheme: InstructionScheme) -> OperationResult<()> {
cpu.bank_apply(scheme.target, scheme.argument.get_range()?, unsigned::quotient);
Ok(())
}
pub fn compare_unsigned(cpu: &mut Cpu, scheme: InstructionScheme) -> OperationResult<()> {
let (a, b) = scheme.argument.get_two_u16()?;
let a_val = cpu.state.bank.get(RegisterId::new(a));
let b_val = cpu.state.bank.get(RegisterId::new(b));
cpu.state.operation.compare = Compare::cmp(a_val, b_val);
cpu.debug("compare", cpu.state.operation.compare.to_string(), "=".to_string());
Ok(())
}
pub fn operation_set() -> OperationSet {
let mut set: OperationSet = HashMap::new();
set.insert(
SUM_UNSIGNED,
Operation::new(SUM_UNSIGNED, "sum-unsigned".to_string(), true, ArgumentType::Range, sum_unsigned),
);
set.insert(
PRODUCT_UNSIGNED,
Operation::new(PRODUCT_UNSIGNED, "product-unsigned".to_string(), true, ArgumentType::Range, product_unsigned),
);
set.insert(
DIFFERENCE_UNSIGNED,
Operation::new(DIFFERENCE_UNSIGNED, "difference-unsigned".to_string(), true, ArgumentType::Range, difference_unsigned),
);
set.insert(
QUOTIENT_UNSIGNED,
Operation::new(QUOTIENT_UNSIGNED, "quotient-unsigned".to_string(), true, ArgumentType::Range, quotient_unsigned),
);
set.insert(
COMPARE_UNSIGNED,
Operation::new(COMPARE_UNSIGNED, "compare-unsigned".to_string(), false, ArgumentType::TwoU16, compare_unsigned),
);
set
}