Website Summary Files Commits Branches @commit @diff @stats
path: root / spasm / src
diff options
context:
space:
mode:
Commite7c2a14f3e424f1ef1109d7634ece820a058e862 (patch)
Author
 Dimitar Trendafilov <dimitar@coherent-labs.com>
2018-11-13 23:52:40 +0200
Committer
 Dimitar Trendafilov <dimitar@coherent-labs.com>
2018-11-13 23:52:40 +0200
Files587a120e78e7c0d50c381d8f38bf0665ed8733a7 /spasm/src
IPL-e7c2a14f3e424f1ef1109d7634ece820a058e862.tar
IPL-e7c2a14f3e424f1ef1109d7634ece820a058e862.tar.gz
IPL-e7c2a14f3e424f1ef1109d7634ece820a058e862.zip
Parentfa077610dfe8b59eb2af069d2f3e92b4790a21d2 (diff)
Implemented call and ret opcodes
6 files changed, 64 insertions, 224 deletions
-rw-r--r--spasm/src/frames.cpp130
-rw-r--r--spasm/src/frames.hpp51
-rw-r--r--spasm/src/main.cpp2
-rw-r--r--spasm/src/spasm.cpp83
-rw-r--r--spasm/src/spasm_impl.hpp19
-rw-r--r--spasm/src/types.hpp3
diff --git a/spasm/src/frames.cpp b/spasm/src/frames.cpp
deleted file mode 100644
index 8b7c891..0000000
--- a/spasm/src/frames.cpp
+++ /dev/null
@@ -1,130 +0,0 @@
-#include <algorithm>
-
-#include "types.hpp"
-
-#include "frames.hpp"
-
-namespace SpasmImpl
-{
-FrameStack::FrameStack() : base_ptr(NULL), frame_ptr(NULL), g_size(0), c_size(0)
-{
-}
-
-FrameStack::FrameStack(const FrameStack& fs)
- : g_size(fs.g_size), c_size(fs.c_size), fstack(fs.fstack)
-{
- copy_fstack(fs);
-}
-
-FrameStack::~FrameStack()
-{
- delete_fstack();
-}
-
-FrameStack& FrameStack::operator=(const FrameStack& fs)
-{
- if (this != &fs)
- {
- delete_fstack();
- copy_fstack(fs);
- g_size = fs.g_size;
- c_size = fs.c_size;
- fstack = fs.fstack;
- }
- return *this;
-}
-
-/*!
-** Deletes the frame stack
-*/
-void FrameStack::delete_fstack()
-{
- if (base_ptr)
- delete[] base_ptr;
-}
-
-/*!
-** Copies the frame stack fs
-**
-** \param fs - the frame stack to be copied
-*/
-void FrameStack::copy_fstack(const FrameStack& fs)
-{
- base_ptr = new data_t[fs.g_size];
- std::copy(fs.base_ptr, fs.frame_ptr + fs.c_size, base_ptr);
- frame_ptr = base_ptr + (fs.frame_ptr - fs.base_ptr);
-}
-
-/*!
-** Returns a data_t object from the current frame
-**
-** \param index - index of the data_t object
-** \return const reference to the object
-*/
-const data_t& FrameStack::operator[](size_t index) const
-{
- return frame_ptr[index];
-}
-
-/*!
-** Returns a data_t object from the current frame
-**
-** \param index - index of the data_t object
-** \return reference to the object
-*/
-data_t& FrameStack::operator[](size_t index)
-{
- return frame_ptr[index];
-}
-
-/*!
-** Removes the current frame from the stack.
-** It is called when a function does return.
-*/
-void FrameStack::pop_frame()
-{
- if (fstack.empty())
- {
- frame_ptr = base_ptr;
- c_size = 0;
- }
- else
- {
- data_t* new_frame_ptr = base_ptr + fstack.top();
- fstack.pop();
- c_size = frame_ptr - new_frame_ptr;
- frame_ptr = new_frame_ptr;
- }
-}
-
-/*!
-** Creates (pushes on the stack) new frame of fsize data_t objects
-**
-** \param fsize - size in data_t objects of the new frame
-*/
-void FrameStack::new_frame(size_t fsize)
-{
- if (frame_ptr + c_size + fsize > base_ptr + g_size)
- {
- size_t new_size = g_size + std::max(g_size, c_size + fsize);
- data_t* new_base = new data_t[new_size];
- if (base_ptr)
- {
- std::copy(base_ptr, frame_ptr + c_size, new_base);
- delete[] base_ptr;
- }
- frame_ptr = new_base + (frame_ptr - base_ptr);
- base_ptr = new_base;
- }
- fstack.push(frame_ptr - base_ptr);
- c_size = fsize;
-}
-
-/*!
-** \return true if the stack is empty
-*/
-bool FrameStack::empty() const
-{
- return frame_ptr == base_ptr && c_size == 0;
-}
-} // namespace SpasmImpl
diff --git a/spasm/src/frames.hpp b/spasm/src/frames.hpp
deleted file mode 100644
index 14d1d14..0000000
--- a/spasm/src/frames.hpp
+++ /dev/null
@@ -1,51 +0,0 @@
-#ifndef FRAMES_HPP
-#define FRAMES_HPP
-
-#include <stack>
-
-#include "types.hpp"
-
-namespace SpasmImpl
-{
-//! Class representing the stack frame for a function
-/*!
-** The class is implemented as a simple stack of frames while each frame
-** is built up by a number of data_t objects
-*/
-class FrameStack
-{
- public:
- FrameStack();
- FrameStack(const FrameStack&);
- ~FrameStack();
- FrameStack& operator=(const FrameStack&);
-
- const data_t& operator[](size_t) const;
- data_t& operator[](size_t);
- void pop_frame();
- void new_frame(size_t);
- bool empty() const;
-
- private:
- //! pointer to the base of the stack
- data_t* base_ptr;
-
- //! pointer to the beginning of the current frame
- data_t* frame_ptr;
-
- //! size of the whole stack in data_t objects
- size_t g_size;
-
- //! size of the current frame in data_t objects
- size_t c_size;
-
- //! stack of the offsets between frames in the stack.
- std::stack<size_t> fstack;
-
- void copy_fstack(const FrameStack&);
- void delete_fstack();
-};
-
-} // namespace SpasmImpl
-
-#endif // #ifndef FRAMES_HPP
diff --git a/spasm/src/main.cpp b/spasm/src/main.cpp
index cc2c831..a6465a6 100644
--- a/spasm/src/main.cpp
+++ b/spasm/src/main.cpp
@@ -24,7 +24,7 @@ int main(int argc, const char* argv[])
std::cout << std::endl;
Spasm::Spasm vm;
- vm.Initialize(len, bytecode.get());
+ vm.Initialize(len, bytecode.get());
vm.run();
diff --git a/spasm/src/spasm.cpp b/spasm/src/spasm.cpp
index 79c72a7..d06552d 100644
--- a/spasm/src/spasm.cpp
+++ b/spasm/src/spasm.cpp
@@ -17,15 +17,15 @@ Spasm::Spasm() {}
** \param _ostr - output stream for the machine
*/
void Spasm::Initialize(PC_t _bc_size,
- const byte* _bytecode,
- std::istream& _istr,
- std::ostream& _ostr)
+ const byte* _bytecode,
+ std::istream& _istr,
+ std::ostream& _ostr)
{
- m_PC = 0;
- m_ByteCode.assign(_bytecode, _bytecode + _bc_size);
- istr = &_istr;
- ostr = &_ostr;
+ m_PC = 0;
+ m_ByteCode.assign(_bytecode, _bytecode + _bc_size);
+ istr = &_istr;
+ ostr = &_ostr;
data_stack.resize(1024);
m_SP = &data_stack[0];
m_FP = &data_stack[0];
@@ -65,6 +65,15 @@ Spasm::RunResult Spasm::run()
push(arg0);
break;
}
+ case OpCodes::Alloc:
+ {
+ const auto count = PC_t(read_reg(size));
+ for (PC_t i = 0; i < count; ++i)
+ {
+ push_data(0);
+ }
+ break;
+ }
case OpCodes::Print:
{
const auto arg0 = read_reg(size);
@@ -77,6 +86,18 @@ Spasm::RunResult Spasm::run()
read(arg0);
break;
}
+ case OpCodes::Call:
+ {
+ const auto arg0 = read_reg(size);
+ call(arg0);
+ break;
+ }
+ case OpCodes::Ret:
+ {
+ const auto arg0 = read_reg(size);
+ ret(arg0);
+ break;
+ }
case OpCodes::Jump:
{
const auto arg0 = read_reg(size);
@@ -97,13 +118,13 @@ Spasm::RunResult Spasm::run()
gofalse(arg0, arg1);
break;
}
- case OpCodes::Const:
- {
- const auto reg = read_reg(size);
- const auto value = read_number(size);
- set_local(reg, value);
- break;
- }
+ case OpCodes::Const:
+ {
+ const auto reg = read_reg(size);
+ const auto value = read_number(size);
+ set_local(reg, value);
+ break;
+ }
case OpCodes::Add:
{
const auto arg0 = read_reg(size);
@@ -298,17 +319,13 @@ void Spasm::go(reg_t a0)
** Function call. A new frame with the specified size is created, the
** return address is saved in the return stack and the new pc is loaded.
*/
-void Spasm::call()
+void Spasm::call(reg_t a0)
{
- assert(false && "not-implemented");
-#if 0
- size_t fs; // new frame size
- return_stack.push(pc); // using the ++pc in run()
- pop_data(&fs, sizeof(fs));
- pop_data(&pc, sizeof(pc));
- frame.new_frame(fs);
- --pc; // the ++pc in run()
-#endif
+ Frame call{m_PC, PC_t(m_FP - &data_stack[0]),
+ m_SP - &data_stack[0] - PC_t(*(m_SP - 1)) - 1};
+ m_Frames.push(std::move(call));
+ m_FP = m_SP - 1;
+ go(a0);
}
/*!
@@ -317,13 +334,12 @@ void Spasm::call()
*/
void Spasm::ret(reg_t reg)
{
- // TODO: Implement
- (void)reg;
-#if 0
- pc = return_stack.top();
- return_stack.pop();
- frame.pop_frame();
-#endif
+ Frame parent = m_Frames.top();
+ m_Frames.pop();
+ m_SP = &data_stack[parent.StackPointer];
+ *(m_SP - 1) = m_FP[reg];
+ m_FP = &data_stack[parent.FramePointer];
+ m_PC = parent.ReturnAddress;
}
/*!
@@ -396,9 +412,8 @@ reg_t Spasm::read_reg(size_t size)
data_t Spasm::read_number(size_t size)
{
- assert(size == 0);
- return m_ByteCode[m_PC++];
+ assert(size == 0);
+ return m_ByteCode[m_PC++];
}
-
} // namespace SpasmImpl
diff --git a/spasm/src/spasm_impl.hpp b/spasm/src/spasm_impl.hpp
index 1e1d3ef..75fb4c4 100644
--- a/spasm/src/spasm_impl.hpp
+++ b/spasm/src/spasm_impl.hpp
@@ -3,7 +3,6 @@
#include <iostream>
-#include "frames.hpp"
#include "types.hpp"
namespace SpasmImpl
@@ -15,6 +14,7 @@ enum OpCodes : char
Pop,
PopTo,
Push,
+ Alloc,
Print,
Read,
Call,
@@ -30,7 +30,10 @@ enum OpCodes : char
Mod,
Less,
LessEq,
+ LastIndex = LessEq,
};
+static_assert(LastIndex < 0x3f, "Too many opcodes");
+
//! The Abstract Stack Machine
/*!
** The machine contains a data stack for operations and control flow and
@@ -74,11 +77,15 @@ class Spasm
//! 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;
+ struct Frame {
+ PC_t ReturnAddress;
+ PC_t FramePointer;
+ PC_t StackPointer;
+ };
- //! Stack for the frame of the functions
- FrameStack frame;
+ typedef std::stack<Frame> FrameStack;
+ //! Stack for function frames
+ FrameStack m_Frames;
//! Input stream for read () operation
std::istream* istr;
@@ -104,7 +111,7 @@ class Spasm
void gofalse(reg_t a0, reg_t a1);
void go(reg_t a0);
- void call();
+ void call(reg_t a0);
void ret(reg_t a0);
void load();
diff --git a/spasm/src/types.hpp b/spasm/src/types.hpp
index ec5a0cb..26450db 100644
--- a/spasm/src/types.hpp
+++ b/spasm/src/types.hpp
@@ -7,10 +7,9 @@
namespace SpasmImpl
{
-typedef unsigned char byte;
+typedef int8_t byte;
typedef size_t PC_t;
typedef int data_t;
-typedef std::stack<PC_t> Rstack_t;
class Spasm;
typedef void (Spasm::*Operation)();