Website Summary Files Commits Branches @commit @diff @stats
path: root / spasm / src / spasm_impl.hpp
blob: 1e1d3ef5872ab0ea3fdfe35c71a9474dd4a70e05 (plain) (blame)
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