const SCRATCH_SIZE: usize = 8192;
const IP_SIZE: u32 = 1;
const STACK_SIZE: u32 = 256;
const EXTRA_STATE_SIZE: u32 = 1;
const START_POS: u32 = IP_SIZE + (3 * STACK_SIZE) + EXTRA_STATE_SIZE;
pub struct Chip {
pub scratch: [u32; SCRATCH_SIZE],
pub memstate: [MemState; SCRATCH_SIZE],
}
pub fn set_chip_mem() -> [u32; SCRATCH_SIZE] {
let mut state = [0; SCRATCH_SIZE];
return state;
}
#[derive(Copy, Clone, Eq, PartialEq)]
pub enum MemState {
rw, waiting_on_channel
}
pub fn set_chip_masks_paused() -> [MemState; SCRATCH_SIZE] {
let mut memstate: [MemState; SCRATCH_SIZE] = [MemState::rw; SCRATCH_SIZE];
memstate[0] = MemState::waiting_on_channel;
return memstate;
}
pub type Address = usize;
pub type Flags = u8;
pub type Stuff = u16;
pub enum LUTSelector {
F,
Nor,
Xq,
Notp,
MaterialNonimplication,
Notq,
Xor,
Nand,
And,
Xnor,
Q,
IfThen, P,
ThenIf,
Or,
T
}
pub enum Instruction {
Nop(),
DivRemIntermediate(Address, Address),
DivRem(Address, Address, Address, Address),
AddCarryIntermediate(Address, Address),
AddCarry(Address, Address, Address, Address),
MulCarryIntermediate(Address, Address),
MulCarry(Address, Address, Address, Address),
SubCarryIntermediate(Address, Address),
SubCarry(Address, Address, Address, Address),
ShiftOverflowIntermediate(Address, Address),
ShiftOverflow(Address, Address, Address, Address),
LUTIntermediate(Address, Address, LUTSelector), LUT(Address, Address, Address, LUTSelector),
PopCnt(Address, Address), SendMessage(Address, Stuff)
}
pub fn attempt_write_memory(mut chip: Chip, address: Address, value: u32) -> Result<u8, u8> {
if address >= SCRATCH_SIZE {
panic!("address >= SCRATCH_SIZE: {}", address);
} else if chip.memstate[address] == MemState::waiting_on_channel {
return Err(0);
}
chip.scratch[address] = value;
return Ok(0);
}
pub fn attempt_read_memory(chip: Chip, address: Address) -> Option<u32> {
if address >= SCRATCH_SIZE || chip.memstate[address] == MemState::waiting_on_channel {
return None
}
return Some(chip.scratch[address]);
}
pub fn get_lut_type(selector: u32) -> LUTSelector {
return match selector {
0 => LUTSelector::F,
1 => LUTSelector::Nor,
2 => LUTSelector::Xq,
3 => LUTSelector::Notp,
4 => LUTSelector::MaterialNonimplication,
5 => LUTSelector::Notq,
6 => LUTSelector::Xor,
7 => LUTSelector::Nand,
8 => LUTSelector::And,
9 => LUTSelector::Xnor,
10 => LUTSelector::Q,
11 => LUTSelector::IfThen,
12 => LUTSelector::P,
13 => LUTSelector::ThenIf,
14 => LUTSelector::Or,
15 => LUTSelector::T,
_ => panic!("Invalid selector.")
}
}
pub fn instruction_decode_partial(cell: u32) -> Instruction {
let selector = cell & ((2^5) - 1);
let left: usize = ((cell & (((2^13) - 1) << 6)) >> 6) as usize;
let right: usize = ((cell & (((2^13) -1) << 19)) >> 19) as usize;
if selector > 23 {
panic!("Invalid instruction.");
}
let insn = match selector {
0 => Instruction::Nop(),
1 => Instruction::DivRemIntermediate(left, right),
2 => Instruction::AddCarryIntermediate(left, right),
3 => Instruction::MulCarryIntermediate(left, right),
4 => Instruction::SubCarryIntermediate(left, right),
5 => Instruction::ShiftOverflowIntermediate(left, right),
6 => Instruction::PopCnt(left, right),
7 => Instruction::SendMessage(left, right as u16),
_ => Instruction::LUTIntermediate(left, right, get_lut_type(selector - 8)),
};
return insn;
}