osiris_set_std/
lib.rs

1//! This crate defines a **standard set** for a future **osiris-machine**.
2//!
3//! Each module has its own **operation prefix** which is one byte long.
4//!
5//! ## Operations
6//! * `0x0000` noop
7//!
8//! ### Control
9//! * `0x0101` [control::jump]:`address`
10//! * `0x0102` [control::call]:`address`
11//! * `0x0103` [control::call_return]
12//! * `0x0104` [control::goto] `direct:32`
13//! * `0x0105` [control::gosub] `direct:32`
14//! * `0x0108` [control::loop_init]:`counter_init`
15//! * `0x0109` [control::next] `direct:32`
16//! * `0x010A` [control::goto_if]:`CMP` `direct:32`
17//! * `0x010B` [control::gosub_if]:`CMP` `direct:32`
18//! * `0x010C` [control::goto_check]:`checked` `direct:32`
19//! * `0x010D` [control::gosub_check]:`checked` `direct:32`
20//! * `0x010E` [control::skip_if]:`CMP`
21//! * `0x010F` [control::skip_check]:`checked`
22//! * `0x01FF` [control::halt]
23//!
24//! ### Registers control
25//! * `0x0201` [registers::set_top]:target top:**32**
26//! * `0x0202` [registers::set_bottom]:target bottom:**32**
27//! * `0x0203` [registers::clear_range]
28//! * `0x0204` [registers::move_to_float]:float unsigned:**16**
29//! * `0x0205` [registers::move_from_float]:unsigned float:**16**
30//! * `0x0210` [registers::push]:unsigned
31//! * `0x0211` [registers::pop]:unsigned
32//! * `0x0220` [registers::get_compare]:target
33//!
34//! ### Memory management
35//! * `0x0301` [memory::store_words]:`target` `[start:end]`
36//! * `0x0302` [memory::load_words]:`target` `[start:end]`
37//! * `0x0303` [memory::get_memory_size]:`target`
38//! * `0x0304` [memory::store_floats]:`target` `[start:end]`
39//! * `0x0305` [memory::load_floats]:`target` `[start:end]`
40//!
41//! ### Logic operations
42//! * `0x0400` [logic::is]:`CMP` `target:16`:`compare:16`
43//! * `0x0401` [logic::not]:`target` 0:`origin:16`
44//! * `0x0402` [logic::or]:`target` `[start:end]`
45//! * `0x0403` [logic::and]:`target` `[start:end]`
46//! * `0x0404` [logic::xor]:`target` `[start:end]`
47//! * `0x0405` [logic::nor]:`target` `[start:end]`
48//! * `0x0406` [logic::nand]:`target` `[start:end]`
49//! * `0x0407` [logic::nxor]:`target` `[start:end]`
50//!
51//! ### Integral arithmetic
52//! * `0x1001` [unsigned_arithmetic::sum_unsigned]:`target` `[start:end]`
53//! * `0x1002` [unsigned_arithmetic::product_unsigned]:`target` `[start:end]`
54//! * `0x1003` [unsigned_arithmetic::difference_unsigned]:`target` `[start:end]`
55//! * `0x1004` [unsigned_arithmetic::quotient_unsigned]:`target` `[start:end]`
56//! * `0x100F` [unsigned_arithmetic::compare_unsigned] `r1:r2`
57
58use osiris_process::operation::{merge, Operation, OperationSet};
59use osiris_process::operation::scheme::{ArgumentType, OperationId};
60
61#[cfg(feature = "control")]
62pub mod control;
63
64#[cfg(feature = "registers")]
65pub mod registers;
66
67#[cfg(feature = "memory")]
68pub mod memory;
69
70#[cfg(feature = "logic")]
71/// 0x04
72pub mod logic;
73
74pub mod range_applications;
75#[cfg(feature = "unsigned")]
76pub mod unsigned_arithmetic;
77
78/// 0x11 Floating point arithmetic (+, -, /, *, rnd(), <=>)
79#[cfg(feature = "floating-point")]
80pub mod float_arithmetic {}
81
82/// Returns the standard operation set.
83///
84/// ## Operations
85/// * `0x0000` noop
86/// * `0x0101` [control::jump]:`address`
87/// * `0x0102` [control::call]:`address`
88/// * `0x0103` return ([control::call_return])
89/// * `0x0104` [control::goto] `direct:32`
90/// * `0x0105` [control::gosub] `direct:32`
91/// * `0x0108` loop:`counter_init` ([control::loop_init])
92/// * `0x0109` [control::next] `direct:32`
93/// * `0x010A` [control::goto_if]:`CMP` `direct:32`
94/// * `0x010B` [control::gosub_if]:`CMP` `direct:32`
95/// * `0x010C` [control::goto_check]:`checked` `direct:32`
96/// * `0x010D` [control::gosub_check]:`checked` `direct:32`
97/// * `0x010E` [control::skip_if]:`CMP`
98/// * `0x010F` [control::skip_check]:`checked`
99/// * `0x01FF` [control::halt]
100///
101///
102/// * `0x0201` [registers::set_top]:target top:**32**
103/// * `0x0202` [registers::set_bottom]:target bottom:**32**
104/// * `0x0203` [registers::clear_range]
105/// * `0x0204` [registers::move_to_float]:float unsigned:**16**
106/// * `0x0205` [registers::move_from_float]:unsigned float:**16**
107/// * `0x0210` [registers::push]:unsigned
108/// * `0x0211` [registers::pop]:unsigned
109/// * `0x0220` [registers::get_compare]:target
110///
111///
112/// * `0x0301` [memory::store_words]:`target` `[start:end]`
113/// * `0x0302` [memory::load_words]:`target` `[start:end]`
114/// * `0x0303` [memory::get_memory_size]:`target`
115/// * `0x0304` [memory::store_floats]:`target` `[start:end]`
116/// * `0x0305` [memory::load_floats]:`target` `[start:end]`
117///
118///
119/// * `0x0400` [logic::is]:`CMP` `target:16`:`compare:16`
120/// * `0x0401` [logic::not]:`target` 0:`origin:16`
121/// * `0x0402` [logic::or]:`target` `[start:end]`
122/// * `0x0403` [logic::and]:`target` `[start:end]`
123/// * `0x0404` [logic::xor]:`target` `[start:end]`
124/// * `0x0405` [logic::nor]:`target` `[start:end]`
125/// * `0x0406` [logic::nand]:`target` `[start:end]`
126/// * `0x0407` [logic::nxor]:`target` `[start:end]`
127///
128///
129/// * `0x1001` [unsigned_arithmetic::sum_unsigned]:`target` `[start:end]`
130/// * `0x1002` [unsigned_arithmetic::product_unsigned]:`target` `[start:end]`
131/// * `0x1003` [unsigned_arithmetic::difference_unsigned]:`target` `[start:end]`
132/// * `0x1004` [unsigned_arithmetic::quotient_unsigned]:`target` `[start:end]`
133/// * `0x100F` [unsigned_arithmetic::compare_unsigned] `r1:r2`
134pub fn get_standard_set() -> OperationSet {
135    merge(&[
136        #[cfg(feature = "control")]
137        control::operation_set(),
138        #[cfg(feature = "registers")]
139        registers::operation_set(),
140        #[cfg(feature = "memory")]
141        memory::operation_set(),
142        #[cfg(feature = "logic")]
143        logic::operation_set(),
144        #[cfg(feature = "unsigned")]
145        unsigned_arithmetic::operation_set(),
146        OperationSet::from([
147            (OperationId::new(0x0000), Operation::new(
148                OperationId::new(0x0000),
149                "noop".to_string(),
150                false,
151                ArgumentType::NoArgument,
152                |_, _| Ok(()),
153            ))
154        ])
155    ])
156}
157
158#[cfg(test)]
159#[cfg(feature = "control")]
160#[cfg(feature = "registers")]
161#[cfg(feature = "unsigned")]
162mod tests {
163    use std::cell::RefCell;
164    use std::rc::Rc;
165    use osiris_data::data::atomic::Word;
166    use osiris_data::data::composite::Array;
167    use osiris_data::data::identification::Address;
168    use osiris_data::memory::Memory;
169    use osiris_process::processor::Cpu;
170    use osiris_process::register::{RegisterBank, RegisterId};
171    use crate::get_standard_set;
172
173    mod instructions_tests;
174
175    #[test]
176    pub fn test_std() {
177        let mut memory = Memory::with_size(1024);
178        memory.copy(Address::new(0), Array::from(&[
179            //                OPID TRGT ARG1 ARG2
180            // 0x0000
181            Word::new(0x0105_0000_0000_0003), // gosub 3
182            // 0x0001
183            Word::new(0x0211_0000_0000_0000), // pop:0
184            // 0x0002
185            Word::new(0x01FF_0000_0000_0000), // halt
186            // 0x0003
187            Word::new(0x0202_0000_0000_0000), // set-bottom:0 0
188            // 0x0004
189            Word::new(0x0202_0001_0000_0001), // set-bottom:1 1
190            // 0x0005
191            Word::new(0x0202_0002_0000_000A), // set-bottom:2 10
192            // 0x0006
193            Word::new(0x0108_0002_0000_0000), // for:2
194            // 0x0007
195            Word::new(0x1001_0000_0000_0001), // sum-unsigned:0 [0:1]
196            // 0x0008
197            Word::new(0x0109_0000_0000_0007), // next 7
198            // 0x0009
199            Word::new(0x0211_0004_0000_0000), // pop:4
200            // 0x000A
201            Word::new(0x0210_0000_0000_0000), // push:0
202            // 0x000B
203            Word::new(0x0210_0004_0000_0000), // push:4
204            // 0x000C
205            Word::new(0x0103_0000_0000_0000), // return
206        ])).expect("");
207        let mut cpu = Cpu::new(RefCell::new(memory), Rc::new(get_standard_set()));
208        cpu.state.flag_debug = true;
209        cpu.until_halt();
210        assert_eq!(cpu.state.bank.get(RegisterId::new(0)).to_u64(), 10);
211    }
212
213}