osiris_set_std/
logic.rs

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
26/// # `0x0400` [is]:`CMP` `target:16`:`compare:16`
27///
28/// ## Target
29///  - CMP : LT(<) / LE(<=) / NE(!=) / EQ(==) / GE(>=) / GT(>)
30///
31/// ## Arguments
32/// - target:register
33/// - compare:register
34///
35/// ## Operation
36///  - `REG[$target] = CMP == $compare`
37///
38/// ## Errors
39///  - [OperationError::InvalidArgumentType] if the provided argument is not an [ArgumentType::TwoU16],
40pub 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
49/// # `0x0401` [not]:`target` 0:`origin:16`
50///
51/// ## Target
52///  - The bank register to write the value of the compare register.
53///
54/// ## Arguments
55/// - 0:`$origin`
56///
57/// ## Operation
58///  - `REG[$target] = not REG[$origin]`
59///
60/// ## Errors
61///  - [OperationError::InvalidArgumentType] if the provided argument is not an [ArgumentType::TwoU16],
62pub 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
69/// # `0x0402` [or]:`target` `[start:end]`
70///
71/// ## Target
72///  - The register to store the result value.
73///
74/// ## Arguments
75/// - The register range onto apply the operator.
76///
77/// ## Operation
78///  - `REG[$target] = 0x00... or REG[start..end]...`
79///
80/// ## Errors
81///  - [OperationError::InvalidArgumentType] if the provided argument is not an [ArgumentType::Range],
82pub 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
96/// # `0x0403` [and]:`target` `[start:end]`
97///
98/// ## Target
99///  - The register to store the result value.
100///
101/// ## Arguments
102/// - The register range onto apply the operator.
103///
104/// ## Operation
105///  - `REG[$target] = 0xFF... and REG[start..end]...`
106///
107/// ## Errors
108///  - [OperationError::InvalidArgumentType] if the provided argument is not an [ArgumentType::Range],
109pub 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
123/// # `0x0404` [xor]:`target` `[start:end]`
124///
125/// ## Target
126///  - The register to store the result value.
127///
128/// ## Arguments
129/// - The register range onto apply the operator.
130///
131/// ## Operation
132///  - `REG[$target] = 0x00... xor REG[start..end]...`
133///
134/// ## Errors
135///  - [OperationError::InvalidArgumentType] if the provided argument is not an [ArgumentType::Range],
136pub 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
150/// # `0x0405` [nor]:`target` `[start:end]`
151///
152/// ## Target
153///  - The register to store the result value.
154///
155/// ## Arguments
156/// - The register range onto apply the operator.
157///
158/// ## Operation
159///  - `REG[$target] = 0x00... nor REG[start..end]...`
160///
161/// ## Errors
162///  - [OperationError::InvalidArgumentType] if the provided argument is not an [ArgumentType::Range],
163pub 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
177/// # `0x0406` [nand]:`target` `[start:end]`
178///
179/// ## Target
180///  - The register to store the result value.
181///
182/// ## Arguments
183/// - The register range onto apply the operator.
184///
185/// ## Operation
186///  - `REG[$target] = 0x00... nand REG[start..end]...`
187///
188/// ## Errors
189///  - [OperationError::InvalidArgumentType] if the provided argument is not an [ArgumentType::Range],
190pub 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
204/// # `0x0407` [nxor]:`target` `[start:end]`
205///
206/// ## Target
207///  - The register to store the result value.
208///
209/// ## Arguments
210/// - The register range onto apply the operator.
211///
212/// ## Operation
213///  - `REG[$target] = 0x00... nxor REG[start..end]...`
214///
215/// ## Errors
216///  - [OperationError::InvalidArgumentType] if the provided argument is not an [ArgumentType::Range],
217pub 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
232/// Returns logic operations.
233///
234/// ## Operations
235///
236/// * `0x0400` [is]:`CMP` `target:16`:`compare:16`
237/// * `0x0401` [not]:`target` 0:`origin:16`
238/// * `0x0402` [or]:`target` `[start:end]`
239/// * `0x0403` [and]:`target` `[start:end]`
240/// * `0x0404` [xor]:`target` `[start:end]`
241/// * `0x0405` [nor]:`target` `[start:end]`
242/// * `0x0406` [nand]:`target` `[start:end]`
243/// * `0x0407` [nxor]:`target` `[start:end]`
244pub 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}