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}