1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
use osiris_process::operation::{merge, Operation, OperationSet};
use osiris_process::operation::scheme::{ArgumentType, OperationId};

pub mod range_applications;
pub mod control;

pub mod registers;

pub mod memory;

/// 0x04
pub mod logic {}

pub mod integral_arithmetic;

/// 0x11 Floating point arithmetic (+, -, /, *, rnd(), <=>)
pub mod float_arithmetic {}

/// Returns the standard operation set.
///
/// ## Operations
/// * `0x0000` noop
/// * `0x0101` [jump]:`address`
/// * `0x0102` [call]:`address`
/// * `0x0103` [call_return]
/// * `0x0104` [goto] `direct`:**32**
/// * `0x0105` [gosub] `direct`:**32**
/// * `0x0108` [for]:`counter_init`
/// * `0x0109` [next] `direct`:**32**
/// * `0x01FF` [halt]
///
///
/// * `0x0201` [set_top]:target top:**32**
/// * `0x0202` [set_bottom]:target bottom:**32**
/// * `0x0203` [clear_range]
/// * `0x0204` [move_to_float]:float unsigned:**16**
/// * `0x0205` [move_from_float]:unsigned float:**16**
/// * `0x0210` [push]:unsigned
/// * `0x0211` [pop]:unsigned
///
///
/// * `0x0301` [store_words]:`target` `[start:end]`
/// * `0x0302` [load_words]:`target` `[start:end]`
/// * `0x0303` [get_memory_size]:`target`
/// * `0x0304` [store_floats]:`target` `[start:end]`
/// * `0x0305` [load_floats]:`target` `[start:end]`
///
///
/// * `0x1001` [sum_integers]:`target` `[start:end]`
/// * `0x1002` [product_integers]:`target` `[start:end]`
/// * `0x1003` [difference_integers]:`target` `[start:end]`
/// * `0x1004` [quotient_integers]:`target` `[start:end]`
pub fn get_standard_set() -> OperationSet {
    merge(&[
        control::operation_set(),
        registers::operation_set(),
        memory::operation_set(),
        integral_arithmetic::operation_set(),
        OperationSet::from([
            (OperationId::new(0x0000), Operation::new(
                OperationId::new(0x0000),
                "noop".to_string(),
                false,
                ArgumentType::NoArgument,
                |_, _| Ok(()),
            ))
        ])
    ])
}

#[cfg(test)]
mod tests {
    use std::cell::RefCell;
    use std::rc::Rc;
    use osiris_data::data::atomic::Word;
    use osiris_data::data::composite::Array;
    use osiris_data::data::identification::Address;
    use osiris_data::memory::Memory;
    use osiris_process::processor::Cpu;
    use osiris_process::register::RegisterId;
    use crate::get_standard_set;

    #[test]
    pub fn test_std() {
        let mut memory = Memory::with_size(1024);
        memory.copy(Address::new(0), Array::from(&[
            //                OPID TRGT ARG1 ARG2
            // 0x0000
            Word::new(0x0105_0000_0000_0003), // gosub 3
            // 0x0001
            Word::new(0x0211_0000_0000_0000), // pop:0
            // 0x0002
            Word::new(0x01FF_0000_0000_0000), // halt
            // 0x0003
            Word::new(0x0202_0000_0000_0000), // set-bottom:0 0
            // 0x0004
            Word::new(0x0202_0001_0000_0001), // set-bottom:1 1
            // 0x0005
            Word::new(0x0202_0002_0000_0004), // set-bottom:2 4
            // 0x0006
            Word::new(0x0108_0002_0000_0000), // for:2
            // 0x0007
            Word::new(0x1001_0000_0000_0001), // sum-unsigned:0 [0:1]
            // 0x0008
            Word::new(0x0109_0000_0000_0007), // next 7
            // 0x0009
            Word::new(0x0211_0004_0000_0000), // pop:4
            // 0x000A
            Word::new(0x0210_0000_0000_0000), // push:0
            // 0x000B
            Word::new(0x0210_0004_0000_0000), // push:4
            // 0x000C
            Word::new(0x0103_0000_0000_0000), // return
        ])).expect("");
        let mut cpu = Cpu::new(RefCell::new(memory), Rc::new(get_standard_set()));
        cpu.state.flag_debug = true;
        cpu.until_halt();
        assert_eq!(cpu.state.bank.get(RegisterId::new(0)).to_u64(), 4);
    }

}