use std::collections::HashMap;
use osiris_data::data::atomic::Word;
use osiris_data::data::composite::Array;
use osiris_data::data::identification::{Address, Area};
use osiris_data::memory::MemoryError;
use osiris_process::operation::error::{OperationError, OperationResult, promote};
use osiris_process::operation::{Operation, OperationSet};
use osiris_process::operation::scheme::{ArgumentType, InstructionScheme, OperationId};
use osiris_process::processor::Cpu;
use osiris_process::register::floating_point::Number;
use osiris_process::register::RegisterBank;
pub const SET_MASK: u16 = 0x0300;
pub const STORE_WORDS: OperationId = OperationId::new(SET_MASK | 0x01);
pub const LOAD_WORDS: OperationId = OperationId::new(SET_MASK | 0x02);
pub const GET_MEMORY_SIZE: OperationId = OperationId::new(SET_MASK | 0x03);
pub const STORE_FLOATS: OperationId = OperationId::new(SET_MASK | 0x04);
pub const LOAD_FLOATS: OperationId = OperationId::new(SET_MASK | 0x05);
pub fn store_words(cpu: &mut Cpu, scheme: InstructionScheme) -> OperationResult<()> {
let range = scheme.argument.get_range()?;
let start = cpu.bank_get(scheme.target);
let chunk = cpu.state.bank.slice(range);
promote(cpu.ram_mut().copy(Address::from_word(start), Array::from(chunk)))
}
pub fn load_words(cpu: &mut Cpu, scheme: InstructionScheme) -> OperationResult<()> {
let range = scheme.argument.get_range()?;
let memory = cpu.memory();
let ram = memory.borrow();
let start = cpu.bank_get(scheme.target).to_u64();
let end = start + range.count() as u64 - 1;
let area = Area::region(Address::new(start), (end - start) as usize);
let slice = promote(ram.slice(area))?;
cpu.state.bank.copy(range.start, slice);
Ok(())
}
pub fn get_memory_size(cpu: &mut Cpu, scheme: InstructionScheme) -> OperationResult<()> {
scheme.argument.get_no_argument()?;
cpu.bank_set(scheme.target, Word::from_usize(cpu.memory_size()));
Ok(())
}
pub fn store_floats(cpu: &mut Cpu, scheme: InstructionScheme) -> OperationResult<()> {
let range = scheme.argument.get_range()?;
let start = cpu.bank_get(scheme.target);
let chunk = cpu.state.vector.slice(range);
promote(cpu.ram_mut().copy(Address::from_word(start), Number::slice_to_array(chunk)))
}
pub fn load_floats(cpu: &mut Cpu, scheme: InstructionScheme) -> OperationResult<()> {
let range = scheme.argument.get_range()?;
let memory = cpu.memory();
let ram = memory.borrow();
let start = cpu.bank_get(scheme.target).to_u64();
let end = start + range.count() as u64 - 1;
let area = Area::region(Address::new(start), (end - start) as usize);
let slice = promote(ram.slice(area))?;
cpu.state.vector.copy(range.start, &Number::from_words_slice(slice));
Ok(())
}
pub fn operation_set() -> OperationSet {
let mut set: OperationSet = HashMap::new();
set.insert(
STORE_WORDS,
Operation::new(STORE_WORDS, "store-words".to_string(), true, ArgumentType::Range, store_words),
);
set.insert(
LOAD_WORDS,
Operation::new(LOAD_WORDS, "load-words".to_string(), true, ArgumentType::Range, load_words),
);
set.insert(
GET_MEMORY_SIZE,
Operation::new(GET_MEMORY_SIZE, "get-memory-size".to_string(), true, ArgumentType::NoArgument, get_memory_size),
);
set.insert(
STORE_FLOATS,
Operation::new(STORE_FLOATS, "store-float".to_string(), true, ArgumentType::Range, store_floats),
);
set.insert(
LOAD_FLOATS,
Operation::new(LOAD_FLOATS, "load-floats".to_string(), true, ArgumentType::Range, load_floats),
);
set
}