diff options
| Commit | e7c2a14f3e424f1ef1109d7634ece820a058e862 (patch) | |
|---|---|---|
| Author | 2018-11-13 23:52:40 +0200 | |
| Committer | 2018-11-13 23:52:40 +0200 | |
| Files | 587a120e78e7c0d50c381d8f38bf0665ed8733a7 /spasm | |
| IPL-e7c2a14f3e424f1ef1109d7634ece820a058e862.tar IPL-e7c2a14f3e424f1ef1109d7634ece820a058e862.tar.gz IPL-e7c2a14f3e424f1ef1109d7634ece820a058e862.zip | ||
| Parent | fa077610dfe8b59eb2af069d2f3e92b4790a21d2 (diff) | |
Implemented call and ret opcodes
9 files changed, 64 insertions, 235 deletions
| -rw-r--r-- | spasm/solution/sprt.make | 6 | ||||
| -rw-r--r-- | spasm/solution/sprt.vcxproj | 2 | ||||
| -rw-r--r-- | spasm/solution/sprt.vcxproj.filters | 3 | ||||
| -rw-r--r-- | spasm/src/frames.cpp | 130 | ||||
| -rw-r--r-- | spasm/src/frames.hpp | 51 | ||||
| -rw-r--r-- | spasm/src/main.cpp | 2 | ||||
| -rw-r--r-- | spasm/src/spasm.cpp | 83 | ||||
| -rw-r--r-- | spasm/src/spasm_impl.hpp | 19 | ||||
| -rw-r--r-- | spasm/src/types.hpp | 3 |
diff --git a/spasm/solution/sprt.make b/spasm/solution/sprt.make index d4ffbe8..10f5b52 100644 --- a/spasm/solution/sprt.make +++ b/spasm/solution/sprt.make @@ -61,7 +61,6 @@ ifeq ($(config),debug64) LINKOBJS = $(OBJECTS) LINKCMD = $(AR) -rcs $(TARGET) OBJECTS := \ - $(OBJDIR)/src/frames.o \ $(OBJDIR)/src/spasm.o \ define PREBUILDCMDS @@ -91,7 +90,6 @@ ifeq ($(config),release64) LINKOBJS = $(OBJECTS) LINKCMD = $(AR) -rcs $(TARGET) OBJECTS := \ - $(OBJDIR)/src/frames.o \ $(OBJDIR)/src/spasm.o \ define PREBUILDCMDS @@ -157,10 +155,6 @@ $(GCH_OBJC): $(PCH) $(MAKEFILE) | $(OBJDIR) $(SILENT) $(CXX) $(ALL_OBJCPPFLAGS) -x objective-c++-header $(DEFINES) $(INCLUDES) -o "$@" -c "$<" endif -$(OBJDIR)/src/frames.o: ../src/frames.cpp $(GCH) $(MAKEFILE) | $(OBJDIR)/src - @echo $(notdir $<) - $(SILENT) $(CXX) $(ALL_CXXFLAGS) $(FORCE_INCLUDE) -o "$@" -c "$<" - $(OBJDIR)/src/spasm.o: ../src/spasm.cpp $(GCH) $(MAKEFILE) | $(OBJDIR)/src @echo $(notdir $<) $(SILENT) $(CXX) $(ALL_CXXFLAGS) $(FORCE_INCLUDE) -o "$@" -c "$<" diff --git a/spasm/solution/sprt.vcxproj b/spasm/solution/sprt.vcxproj index 9ffa6d1..2698c10 100644 --- a/spasm/solution/sprt.vcxproj +++ b/spasm/solution/sprt.vcxproj @@ -112,8 +112,6 @@ <ItemGroup>
<ClCompile Include="..\src\spasm.cpp">
</ClCompile>
- <ClCompile Include="..\src\frames.cpp">
- </ClCompile>
</ItemGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
<ImportGroup Label="ExtensionTargets">
diff --git a/spasm/solution/sprt.vcxproj.filters b/spasm/solution/sprt.vcxproj.filters index 02c2afd..d9f8e3a 100644 --- a/spasm/solution/sprt.vcxproj.filters +++ b/spasm/solution/sprt.vcxproj.filters @@ -9,8 +9,5 @@ <ClCompile Include="..\src\spasm.cpp">
<Filter>src</Filter>
</ClCompile>
- <ClCompile Include="..\src\frames.cpp">
- <Filter>src</Filter>
- </ClCompile>
</ItemGroup>
</Project>
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)(); |
