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
122
123
124
125
|
#ifndef SPASM_IMPL_HPP
#define SPASM_IMPL_HPP
#include <iostream>
#include "frames.hpp"
#include "types.hpp"
namespace SpasmImpl
{
enum OpCodes : char
{
Halt,
Dup,
Pop,
PopTo,
Push,
Print,
Read,
Call,
Ret,
Jump,
JumpT,
JumpF,
Const,
Add,
Sub,
Mul,
Div,
Mod,
Less,
LessEq,
};
//! The Abstract Stack Machine
/*!
** The machine contains a data stack for operations and control flow and
** frame stack for function calls (including parameter passing) and local
** variables and return stack for the addresses of the returns.
*/
class Spasm
{
public:
Spasm();
void Initialize(PC_t,
const byte*,
std::istream& = std::cin,
std::ostream& = std::cout);
~Spasm();
Spasm(const Spasm&) = delete;
Spasm& operator=(const Spasm&) = delete;
enum RunResult {
Success,
Exception,
NotImplemented,
};
RunResult run();
private:
//! Program counter - points the current opcode
PC_t m_PC = 0;
typedef SPVector<byte> ByteCode;
//! bytecode of the program
ByteCode m_ByteCode;
typedef SPVector<data_t> DataStack;
//! stack for storing arguments and local variables
DataStack data_stack;
//! Stack pointer - always the top of the stack
data_t* m_SP = nullptr;
//! Frame pointer - the start of the stack for the current function
data_t* m_FP = nullptr;
//! Return stack for the addresses of the returns
Rstack_t return_stack;
//! Stack for the frame of the functions
FrameStack frame;
//! Input stream for read () operation
std::istream* istr;
//! Output stream for print () opertion
std::ostream* ostr;
void push(reg_t reg);
void pop(reg_t reg);
void pop();
void dup();
void print(reg_t reg);
void read(reg_t reg);
void plus(reg_t a0, reg_t a1, reg_t a2);
void minus(reg_t a0, reg_t a1, reg_t a2);
void multiply(reg_t a0, reg_t a1, reg_t a2);
void divide(reg_t a0, reg_t a1, reg_t a2);
void modulus(reg_t a0, reg_t a1, reg_t a2);
void gotrue(reg_t a0, reg_t a1);
void gofalse(reg_t a0, reg_t a1);
void go(reg_t a0);
void call();
void ret(reg_t a0);
void load();
void store();
void less(reg_t a0, reg_t a1, reg_t a2);
void lesseq(reg_t a0, reg_t a1, reg_t a2);
data_t get_local(reg_t reg);
void set_local(reg_t reg, data_t data);
data_t pop_data();
void push_data(data_t);
reg_t read_reg(size_t size);
data_t read_number(size_t size);
};
} // namespace SpasmImpl
#endif // #ifndef SPASM_IMPL_HPP
|