tower_vm/interpreter/
instruction.rs

1#[repr(u8)]
2#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord)]
3pub enum Instruction {
4    // machine control instructions
5    Halt,    // stop execution
6    SetType, // set the type flag the value of the next byte
7    GetType, // push the type flag to the stack as a byte
8
9    // arithmetic instructions: pop two values, convert to the type flag, perform the operation, push the result
10    Add,
11    Sub,
12    Mul,
13    Div,
14    Rem,
15
16    // Neg does not pop a value, it just negates the top of the stack
17    Neg,
18
19    // incr and decr don't pop a value, they just increment or decrement the top of the stack
20    // will probably throw err if called on a non-integer type
21    // good for control flow, address arithmetic, etc.
22    Incr,
23    Decr,
24
25    // comparison instructions: pop two values, perform the comparison, push boolean result
26    Eq,
27    Neq,
28    Lt,
29    Gt,
30    Lte,
31    Gte,
32
33    // bitwise instructions: pop two values, perform the operation, push the result
34    And,
35    Or,
36    Xor,
37    Shl,
38    Shr,
39
40    // bitwise not does not pop a value, it just negates the top of the stack
41    Not,
42
43    // control flow
44    Jmp,      // set ip to address popped from stack
45    JmpIf, // pop two values, if the first is true, set ip to the second, otherwise continue (type flag is ignored everything is treated as u64)
46    JmpIfNot, // pop two values, if the first is false, set ip to the second, otherwise continue (type flag is ignored everything is treated as u64)
47
48    // function call instructions
49    Call, // pop address from stack, push return address, set ip to address
50    Ret,  // pop return address from stack, set ip to address (same as jmp, but rather be explicit)
51
52    // stack manipulation instructions
53    Push, // based on the type flag, read the following bytes from the code and push them to the stack, and adjust the ip by the number of bytes read
54    Dup,  // duplicate the top of the stack
55    Drop, // drop the top of the stack
56    Swap, // swap the top two values on the stack
57
58    // heap instructions
59    Load,  // pop address from stack and push value at address using the current alignment
60    Store, // pop value and address from stack, store value at address as bytes
61    Alloc, // pop size from stack, expand heap by sizeof(current type flag) * size, push first address of new heap space
62    Free,  // pop address from stack, decrement heap size by sizeof(current type flag) * size
63    HeapSize, // push heap size to stack
64    StackSize, // push stack size to stack
65
66    // meta instructions
67    // these instructions are used for loading code into the interpreter
68    LoadCode, // pop two addresses from stack, take the bytes between the addresses on the heap and extend the code segment with them, and push the address of the new code segment to the stack
69    SaveCode, // pop two addresses from stack, take the bytes between the addresses on the code segment and extend the heap with them, and push the address of the new heap segment to the stack
70
71    // io instructions
72    Read, // halts execution and awaits input to the stream
73    Write, // pops a value from the stack and writes it to the stream
74    Print, // print the stream
75    Clear, // clear the stream
76}
77
78impl From<u8> for Instruction {
79    fn from(value: u8) -> Self {
80        use Instruction::*;
81
82        match value {
83            0 => Halt,
84            1 => SetType,
85            2 => GetType,
86            3 => Add,
87            4 => Sub,
88            5 => Mul,
89            6 => Div,
90            7 => Rem,
91            8 => Neg,
92            9 => Incr,
93            10 => Decr,
94            11 => Eq,
95            12 => Neq,
96            13 => Lt,
97            14 => Gt,
98            15 => Lte,
99            16 => Gte,
100            17 => And,
101            18 => Or,
102            19 => Xor,
103            20 => Shl,
104            21 => Shr,
105            22 => Not,
106            23 => Jmp,
107            24 => JmpIf,
108            25 => JmpIfNot,
109            26 => Call,
110            27 => Ret,
111            28 => Push,
112            29 => Dup,
113            30 => Drop,
114            31 => Swap,
115            32 => Load,
116            33 => Store,
117            34 => Alloc,
118            35 => Free,
119            36 => HeapSize,
120            37 => StackSize,
121            38 => LoadCode,
122            39 => SaveCode,
123            40 => Read,
124            41 => Write,
125            42 => Print,
126            43 => Clear,
127            _ => panic!("invalid instruction"),
128        }
129    }
130}