1use std::collections::HashMap;
2use osiris_data::converters::Words;
3use osiris_data::data::atomic::Word;
4use osiris_process::compare::Compare;
5use osiris_process::operation::{Operation, OperationSet};
6use osiris_process::operation::error::{OperationError, OperationResult};
7use osiris_process::operation::scheme::{ArgumentType, InstructionScheme, OperationId};
8use osiris_process::processor::Cpu;
9use osiris_process::register::RegisterId;
10use crate::range_applications::reduce;
11
12pub const TRUE: Word = Word::new(0xFFFFFFFFFFFFFFFF);
13pub const FALSE: Word = Word::new(0x0);
14
15pub const SET_MASK: u16 = 0x0400;
16
17pub const IS: OperationId = OperationId::new(SET_MASK | 0x00);
18pub const NOT: OperationId = OperationId::new(SET_MASK | 0x01);
19pub const OR: OperationId = OperationId::new(SET_MASK | 0x02);
20pub const AND: OperationId = OperationId::new(SET_MASK | 0x03);
21pub const XOR: OperationId = OperationId::new(SET_MASK | 0x04);
22pub const NOR: OperationId = OperationId::new(SET_MASK | 0x05);
23pub const NAND: OperationId = OperationId::new(SET_MASK | 0x06);
24pub const NXOR: OperationId = OperationId::new(SET_MASK | 0x07);
25
26pub fn is(cpu: &mut Cpu, scheme: InstructionScheme) -> OperationResult<()> {
41 let (target, compare) = scheme.argument.get_two_u16()?;
42 let compare = Words::i64(cpu.bank_get(RegisterId::new(compare)));
43 let cmp = Compare::from(scheme.target.to_u16());
44 let result = cmp.unwrap().is(compare);
45 cpu.bank_set(RegisterId::new(target), if result { TRUE } else { FALSE });
46 Ok(())
47}
48
49pub fn not(cpu: &mut Cpu, scheme: InstructionScheme) -> OperationResult<()> {
63 let (_, origin) = scheme.argument.get_two_u16()?;
64 let origin = RegisterId::new(origin);
65 cpu.bank_set(scheme.target, Word::new(!cpu.bank_get(origin).to_u64()));
66 Ok(())
67}
68
69pub fn or(cpu: &mut Cpu, scheme: InstructionScheme) -> OperationResult<()> {
83 let range = scheme.argument.get_range()?;
84 cpu.bank_apply(
85 scheme.target,
86 range,
87 |slice| reduce(
88 slice,
89 |carry, current| Word::new(carry.to_u64() | current.to_u64()),
90 FALSE,
91 ),
92 );
93 Ok(())
94}
95
96pub fn and(cpu: &mut Cpu, scheme: InstructionScheme) -> OperationResult<()> {
110 let range = scheme.argument.get_range()?;
111 cpu.bank_apply(
112 scheme.target,
113 range,
114 |slice| reduce(
115 slice,
116 |carry, current| Word::new(carry.to_u64() & current.to_u64()),
117 TRUE,
118 ),
119 );
120 Ok(())
121}
122
123pub fn xor(cpu: &mut Cpu, scheme: InstructionScheme) -> OperationResult<()> {
137 let range = scheme.argument.get_range()?;
138 cpu.bank_apply(
139 scheme.target,
140 range,
141 |slice| reduce(
142 slice,
143 |carry, current| Word::new(carry.to_u64() ^ current.to_u64()),
144 FALSE,
145 ),
146 );
147 Ok(())
148}
149
150pub fn nor(cpu: &mut Cpu, scheme: InstructionScheme) -> OperationResult<()> {
164 let range = scheme.argument.get_range()?;
165 cpu.bank_apply(
166 scheme.target,
167 range,
168 |slice| reduce(
169 slice,
170 |carry, current| Word::new(!(carry.to_u64() | current.to_u64())),
171 TRUE,
172 ),
173 );
174 Ok(())
175}
176
177pub fn nand(cpu: &mut Cpu, scheme: InstructionScheme) -> OperationResult<()> {
191 let range = scheme.argument.get_range()?;
192 cpu.bank_apply(
193 scheme.target,
194 range,
195 |slice| reduce(
196 slice,
197 |carry, current| Word::new(!(carry.to_u64() & current.to_u64())),
198 FALSE,
199 ),
200 );
201 Ok(())
202}
203
204pub fn nxor(cpu: &mut Cpu, scheme: InstructionScheme) -> OperationResult<()> {
218 let range = scheme.argument.get_range()?;
219 cpu.bank_apply(
220 scheme.target,
221 range,
222 |slice| reduce(
223 slice,
224 |carry, current| Word::new(!(carry.to_u64() ^ current.to_u64())),
225 TRUE,
226 ),
227 );
228 Ok(())
229}
230
231
232pub fn operation_set() -> OperationSet {
245 let mut set: OperationSet = HashMap::new();
246
247 set.insert(IS, Operation::new(IS, "is".to_string(), true, ArgumentType::TwoU16, is));
248 set.insert(NOT, Operation::new(NOT, "not".to_string(), true, ArgumentType::TwoU16, not));
249 set.insert(OR, Operation::new(OR, "or".to_string(), true, ArgumentType::Range, or));
250 set.insert(AND, Operation::new(AND, "and".to_string(), true, ArgumentType::Range, and));
251 set.insert(XOR, Operation::new(XOR, "xor".to_string(), true, ArgumentType::Range, xor));
252 set.insert(NOR, Operation::new(NOR, "nor".to_string(), true, ArgumentType::Range, nor));
253 set.insert(NAND, Operation::new(NAND, "nand".to_string(), true, ArgumentType::Range, nand));
254 set.insert(NXOR, Operation::new(NXOR, "nxor".to_string(), true, ArgumentType::Range, nxor));
255
256 set
257}