From 835c84c9442fa807074448fefb7319a931fb1765 Mon Sep 17 00:00:00 2001 From: WeebDataHoarder <57538841+weebdatahoarder@users.noreply.github.com> Date: Tue, 3 Aug 2021 00:02:49 +0200 Subject: [PATCH] Major overhaul of Stack system and calling convention, added PUSH, PUT, GET (and immediate versions), optimized FastCall, expanded RET * Stack redesigned to have a Stack pointer and Frame pointer, and restoration of such for ease of access * Can now directly add parameters to RET for setting RRET * PUT, GET (and immediate versions) ops have been added to interact with stack offsets without pushing/popping * New PUSH op to push values onto stack, and PushGroup optimized multiple value set * FastCall now uses optimized PushGroup and minimizes amount of PUSH calls --- asm/stdlib.asm | 62 +++++---- src/instructions/Instruction.cpp | 14 +- src/instructions/virtual/Call.cpp | 22 +++ src/instructions/virtual/Call.h | 4 +- src/instructions/virtual/FastCall.cpp | 77 +++++------ src/instructions/virtual/Stack.cpp | 191 +++++++++++++++++++++++--- src/instructions/virtual/Stack.h | 113 ++++++++++++++- src/rrcas.cpp | 6 + 8 files changed, 399 insertions(+), 90 deletions(-) diff --git a/asm/stdlib.asm b/asm/stdlib.asm index e38067e..631d9f8 100644 --- a/asm/stdlib.asm +++ b/asm/stdlib.asm @@ -12,22 +12,22 @@ .constant P0 std_PARAMETER_0 .constant P1 std_PARAMETER_1 -; These are offset registers to be called with ~3 to access stack parameters -.constant P2 %1, +1 ; Equivalent to same address in POPP , 1 -.constant P3 %1, +2 ; Equivalent to same address in POPP , 2 -.constant P4 %1, +3 ; Equivalent to same address in POPP , 3 -.constant P5 %1, +4 ; Equivalent to same address in POPP , 4 -.constant P6 %1, +5 ; Equivalent to same address in POPP , 5 -.constant P7 %1, +6 ; Equivalent to same address in POPP , 6 -.constant P8 %1, +7 ; Equivalent to same address in POPP , 7 -.constant P9 %1, +8 ; Equivalent to same address in POPP , 8 -.constant P10 %1, +9 ; Equivalent to same address in POPP , 9 -.constant P11 %1, +10 ; Equivalent to same address in POPP , 10 -.constant P12 %1, +11 ; Equivalent to same address in POPP , 11 -.constant P13 %1, +12 ; Equivalent to same address in POPP , 12 -.constant P14 %1, +13 ; Equivalent to same address in POPP , 13 -.constant P15 %1, +14 ; Equivalent to same address in POPP , 14 -.constant P16 %1, +15 ; Equivalent to same address in POPP , 15 +; These are offset registers to be called with ~2 to access stack frame parameters +.constant P2 %0, +1 ; Equivalent to same address in GET , 1 +.constant P3 %0, +2 ; Equivalent to same address in GET , 2 +.constant P4 %0, +3 ; Equivalent to same address in GET , 3 +.constant P5 %0, +4 ; Equivalent to same address in GET , 4 +.constant P6 %0, +5 ; Equivalent to same address in GET , 5 +.constant P7 %0, +6 ; Equivalent to same address in GET , 6 +.constant P8 %0, +7 ; Equivalent to same address in GET , 7 +.constant P9 %0, +8 ; Equivalent to same address in GET , 8 +.constant P10 %0, +9 ; Equivalent to same address in GET , 9 +.constant P11 %0, +10 ; Equivalent to same address in GET , 10 +.constant P12 %0, +11 ; Equivalent to same address in GET , 11 +.constant P13 %0, +12 ; Equivalent to same address in GET , 12 +.constant P14 %0, +13 ; Equivalent to same address in GET , 13 +.constant P15 %0, +14 ; Equivalent to same address in GET , 14 +.constant P16 %0, +15 ; Equivalent to same address in GET , 15 ; Ephemeral registers to be used within functions. These values may not be kept when calling other functions. They can be used when returning values if necessary. ; Some std functions might restore these values. @@ -41,12 +41,12 @@ .constant std_EPHEMERAL_REGISTER_7 std_EPHEMERAL_REGISTER_0 +0x7 .constant std_EPHEMERAL_REGISTER_8 std_EPHEMERAL_REGISTER_0 +0x8 .constant std_EPHEMERAL_REGISTER_9 std_EPHEMERAL_REGISTER_0 +0x9 -.constant std_EPHEMERAL_REGISTER_A std_EPHEMERAL_REGISTER_0 +0xa -.constant std_EPHEMERAL_REGISTER_B std_EPHEMERAL_REGISTER_0 +0xb -.constant std_EPHEMERAL_REGISTER_C std_EPHEMERAL_REGISTER_0 +0xc -.constant std_EPHEMERAL_REGISTER_D std_EPHEMERAL_REGISTER_0 +0xd -.constant std_EPHEMERAL_REGISTER_E std_EPHEMERAL_REGISTER_0 +0xe -.constant std_EPHEMERAL_REGISTER_F std_EPHEMERAL_REGISTER_0 +0xf +.constant std_EPHEMERAL_REGISTER_10 std_EPHEMERAL_REGISTER_0 +0xa +.constant std_EPHEMERAL_REGISTER_11 std_EPHEMERAL_REGISTER_0 +0xb +.constant std_EPHEMERAL_REGISTER_12 std_EPHEMERAL_REGISTER_0 +0xc +.constant std_EPHEMERAL_REGISTER_13 std_EPHEMERAL_REGISTER_0 +0xd +.constant std_EPHEMERAL_REGISTER_14 std_EPHEMERAL_REGISTER_0 +0xe +.constant std_EPHEMERAL_REGISTER_15 std_EPHEMERAL_REGISTER_0 +0xf ; Abbreviations .constant R0 std_EPHEMERAL_REGISTER_0 .constant R1 std_EPHEMERAL_REGISTER_1 @@ -58,12 +58,13 @@ .constant R7 std_EPHEMERAL_REGISTER_7 .constant R8 std_EPHEMERAL_REGISTER_8 .constant R9 std_EPHEMERAL_REGISTER_9 -.constant RA std_EPHEMERAL_REGISTER_A -.constant RB std_EPHEMERAL_REGISTER_B -.constant RC std_EPHEMERAL_REGISTER_C -.constant RD std_EPHEMERAL_REGISTER_D -.constant RE std_EPHEMERAL_REGISTER_E -.constant RF std_EPHEMERAL_REGISTER_F +.constant R10 std_EPHEMERAL_REGISTER_10 +.constant R11 std_EPHEMERAL_REGISTER_11 +.constant R12 std_EPHEMERAL_REGISTER_12 +.constant R13 std_EPHEMERAL_REGISTER_13 +.constant R14 std_EPHEMERAL_REGISTER_14 +.constant R15 std_EPHEMERAL_REGISTER_15 + ; FASTCALL uint std_multiply(uint A, uint B). Return value on RRET ; Uses simple addition @@ -81,3 +82,8 @@ std_multiply: POP BSM_COUNTER_0 ; Restore old value of counter RET ; Return, no need to get rid of stack as fastcall passed them on registers + +; x86-like definitions +.constant ebp, rrcc_FRAME_POINTER +.constant esp, rrcc_STACK_POINTER +.constant eax, RRET \ No newline at end of file diff --git a/src/instructions/Instruction.cpp b/src/instructions/Instruction.cpp index 782e895..66702f5 100644 --- a/src/instructions/Instruction.cpp +++ b/src/instructions/Instruction.cpp @@ -26,6 +26,7 @@ *****************************************************************************/ #include +#include #include "Instruction.h" #include "Write.h" @@ -58,6 +59,10 @@ namespace Instruction { addOperator("POP", 1, Stack::Pop::fromTokens); addOperator("POPI", 0, Stack::PopImm::fromTokens); addOperator("POPP", 1, Stack::PopPeek::fromTokens); + addOperator("PUSH", 1, Stack::Push::fromTokens); + + addOperator("GET", 1, Stack::Get::fromTokens); + addOperator("PUT", 1, Stack::Put::fromTokens); addOperator("CALL", 1, Call::fromTokens); addOperator("RET", 0, Ret::fromTokens); @@ -73,8 +78,6 @@ namespace Instruction { } }); - addOperator("PUSH", 1, Stack::Push::fromTokens); - addOperator("JUMP", 1, Jump::fromTokens); addOperator("RETURN", 1, Return::fromTokens); @@ -154,8 +157,13 @@ namespace Instruction { std::vector tokens(declaration.tokens.begin() + offset, declaration.tokens.end()); + std::string opName = operatorData.name; + for (auto & c: opName){ + c = std::toupper(c); + } + for (auto &e : knownOperators) { - if (e.name == operatorData.name && tokens.size() >= e.minParams) { + if (e.name == opName && tokens.size() >= e.minParams) { return e.callable(operatorData, tokens); } } diff --git a/src/instructions/virtual/Call.cpp b/src/instructions/virtual/Call.cpp index 43e7b46..daa35e6 100644 --- a/src/instructions/virtual/Call.cpp +++ b/src/instructions/virtual/Call.cpp @@ -29,6 +29,8 @@ #include "Call.h" #include "../Return.h" #include "../Jump.h" +#include "../Copy.h" +#include "../Write.h" #include "Stack.h" @@ -78,9 +80,29 @@ namespace Instruction { std::unique_ptr Ret::fromTokens(const Instruction::Instruction::parseOperatorResult &op, const std::vector &tokens) { + if(!tokens.empty()){ + const auto& t = tokens.at(0); + if(t.getType() == Token::Type::RegisterLocation){ + return std::make_unique(AddressWithOffset{t.getNumericValue(), op.offset1}); + } else { + return std::make_unique(t.getNumericValue()); + } + } return std::make_unique(); } + Ret::Ret(const AddressWithOffset &address) { + instructions.push_back(std::make_unique(AddressWithOffset{(uint32_t)MgmtRegisters::MGMT_SCRATCH_0, 0}, address, 1)); + instructions.push_back(std::make_unique(1)); + instructions.push_back(std::make_unique(AddressWithOffset{0, Stack::stackOffsetRegister})); + } + + Ret::Ret(uint32_t value) { + instructions.push_back(std::make_unique(AddressWithOffset{(uint32_t)MgmtRegisters::MGMT_SCRATCH_0, 0}, std::vector({value}))); + instructions.push_back(std::make_unique(1)); + instructions.push_back(std::make_unique(AddressWithOffset{0, Stack::stackOffsetRegister})); + } + Ret::Ret() { instructions.push_back(std::make_unique(1)); instructions.push_back(std::make_unique(AddressWithOffset{0, Stack::stackOffsetRegister})); diff --git a/src/instructions/virtual/Call.h b/src/instructions/virtual/Call.h index 3167bc5..564e3bf 100644 --- a/src/instructions/virtual/Call.h +++ b/src/instructions/virtual/Call.h @@ -49,7 +49,7 @@ namespace Instruction { std::vector toBytes() const override; size_t getByteSize() const override{ - //TODO: do not hardcode this + //TODO: do not hardcode this, or call toBytes return 4 + 8 + 12; //4 bytes for Return/Jump + 8 bytes for Write + 12 for CalcImm } @@ -61,6 +61,8 @@ namespace Instruction { public: explicit Ret(); + explicit Ret(const AddressWithOffset &address); + explicit Ret(uint32_t value); CommandOp getCommand() const override { return CommandOp::END; diff --git a/src/instructions/virtual/FastCall.cpp b/src/instructions/virtual/FastCall.cpp index 05ed0af..a6260a6 100644 --- a/src/instructions/virtual/FastCall.cpp +++ b/src/instructions/virtual/FastCall.cpp @@ -30,6 +30,7 @@ #include "Call.h" #include "../Copy.h" #include "../Write.h" +#include "../CalcImm.h" namespace Instruction{ @@ -56,62 +57,58 @@ namespace Instruction{ } void FastCall::takedownData(const std::vector &data) { - if(data.size() > 2){ - instructions.push_back(std::make_unique(data.size() - 2)); - } + instructions.push_back(std::make_unique(AddressWithOffset{Stack::frameOffsetRegisterAddress, 0}, AddressWithOffset{1, Stack::stackOffsetRegister}, 1)); + instructions.push_back(std::make_unique(1 + (data.size() > 2 ? data.size() - 2 : 0))); } void FastCall::initData(const std::vector &data) { - bool isAllData = true; + + std::vector>> groupData; + + uint32_t offset = 0; for(auto& t : data){ - if(t.getType() == Token::Type::RegisterLocation){ - isAllData = false; + if(offset >= 2){ break; + }else{ + if(t.getType() == Token::Type::RegisterLocation){ + instructions.push_back(std::make_unique(AddressWithOffset{(uint32_t)MgmtRegisters::MGMT_SCRATCH_0 + offset, 0}, AddressWithOffset{t.getNumericValue(), 0}, 1)); //TODO: allow offsets + }else{ + instructions.push_back(std::make_unique(AddressWithOffset{(uint32_t)MgmtRegisters::MGMT_SCRATCH_0 + offset, 0}, std::vector{t.getNumericValue()})); + } } + ++offset; } - if(isAllData){ - std::vector scratchData; - std::vector stackData; - for(uint32_t i = 0; i < data.size(); ++i){ - if(i < 2){ - scratchData.push_back(data.at(i).getNumericValue()); + if(data.size() > 2){ + + for(uint32_t i = 2; i < data.size(); ++i){ + auto& t = data.at(i); + if(t.getType() == Token::Type::RegisterLocation){ + groupData.push_back({Stack::PushGroup::Kind::Address, {1,AddressWithOffset{t.getNumericValue(), 0}}}); //TODO: allow offsets }else{ - stackData.push_back(data.at(i).getNumericValue()); + groupData.push_back({Stack::PushGroup::Kind::Immediate, {t.getNumericValue(),AddressWithOffset{0, 0}}}); } } - instructions.push_back(std::make_unique(AddressWithOffset{(uint32_t)MgmtRegisters::MGMT_SCRATCH_0, 0}, scratchData)); - if(!stackData.empty()){ - instructions.push_back(std::make_unique(stackData)); - } - }else{ - uint32_t offset = 0; - for(auto& t : data){ - if(offset >= 2){ - break; - }else{ - if(t.getType() == Token::Type::RegisterLocation){ - instructions.push_back(std::make_unique(AddressWithOffset{(uint32_t)MgmtRegisters::MGMT_SCRATCH_0 + offset, 0}, AddressWithOffset{t.getNumericValue(), 0}, 1)); //TODO: allow offsets - }else{ - instructions.push_back(std::make_unique(AddressWithOffset{(uint32_t)MgmtRegisters::MGMT_SCRATCH_0 + offset, 0}, std::vector{t.getNumericValue()})); - } - } - ++offset; - } - if(data.size() > 2){ - //Left to right - for(uint32_t i = data.size() - 1; i >= 2; --i){ - auto& t = data.at(i); - if(t.getType() == Token::Type::RegisterLocation){ - instructions.push_back(std::make_unique(AddressWithOffset{t.getNumericValue(), 0})); //TODO: allow offsets - }else{ - instructions.push_back(std::make_unique(t.getNumericValue())); - } + /* + // This uses single push per operation, reverse, left to right + for(uint32_t i = data.size() - 1; i >= 2; --i){ + auto& t = data.at(i); + if(t.getType() == Token::Type::RegisterLocation){ + instructions.push_back(std::make_unique(AddressWithOffset{t.getNumericValue(), 0})); //TODO: allow offsets + }else{ + instructions.push_back(std::make_unique(t.getNumericValue())); } } + */ } + groupData.push_back({Stack::PushGroup::Kind::Address, {1, AddressWithOffset{Stack::frameOffsetRegisterAddress, 0}}}); + + instructions.push_back(std::make_unique(groupData)); + + //instructions.push_back(std::make_unique(AddressWithOffset{Stack::frameOffsetRegisterAddress, 0})); + instructions.push_back(std::make_unique(Calc::Operation::SUB, 0, Stack::frameOffsetRegisterAddress, Stack::stackOffsetRegisterAddress, 1)); } std::unique_ptr FastCall::fromTokens(const Instruction::parseOperatorResult &op, const std::vector &tokens) { diff --git a/src/instructions/virtual/Stack.cpp b/src/instructions/virtual/Stack.cpp index d020133..9f7e9ab 100644 --- a/src/instructions/virtual/Stack.cpp +++ b/src/instructions/virtual/Stack.cpp @@ -27,6 +27,7 @@ #include +#include #include "Stack.h" #include "../Write.h" #include "../Load.h" @@ -36,7 +37,18 @@ namespace Instruction { namespace Stack { - std::vector PushImm::toBytes() const { + + PutImm::PutImm(uint32_t param, const std::vector &value) { + if (value.size() > 16) { + instructions.push_back( + std::make_unique(AddressWithOffset{param, frameOffsetRegister}, 1, value)); + } else { + instructions.push_back( + std::make_unique(AddressWithOffset{param, frameOffsetRegister}, value)); + } + } + + std::vector PutImm::toBytes() const { std::vector v; for (auto &i : instructions) { auto b = i->toBytes(); @@ -45,6 +57,66 @@ namespace Instruction { return v; } + + + Put::Put(uint32_t param, const AddressWithOffset &address, uint8_t count) { + if (count > 4) { + throw std::runtime_error("Put address count cannot be larger than 4 words at once"); + } + instructions.push_back( + std::make_unique(AddressWithOffset{param, frameOffsetRegister}, address, count)); + } + + std::vector Put::toBytes() const { + std::vector v; + for (auto &i : instructions) { + auto b = i->toBytes(); + v.insert(v.end(), b.begin(), b.end()); + } + return v; + } + + std::unique_ptr Put::fromTokens(const Instruction::Instruction::parseOperatorResult &op, + const std::vector &tokens) { + if (tokens.at(0).getType() == Token::Type::RegisterLocation) { + return std::make_unique(tokens.at(0).getNumericValue(), AddressWithOffset{tokens.at(1).getNumericValue(), op.offset1}, tokens.size() >= 3 ? tokens.at(2).getNumericValue() : 1); + } else { + std::vector data; + for (auto it = tokens.begin() + 1; it != tokens.end(); ++it) { + data.emplace_back(it->getNumericValue()); + } + return std::make_unique(tokens.at(0).getNumericValue(), data); + } + } + + + Get::Get(const AddressWithOffset &address, uint32_t param, uint8_t count) { + if (count > 4) { + throw std::runtime_error("Get count cannot be larger than 4 words at once"); + } + instructions.push_back( + std::make_unique(address, AddressWithOffset{param, frameOffsetRegister}, count)); + } + + std::vector Get::toBytes() const { + std::vector v; + for (auto &i : instructions) { + auto b = i->toBytes(); + v.insert(v.end(), b.begin(), b.end()); + } + return v; + } + + std::unique_ptr Get::fromTokens(const Instruction::Instruction::parseOperatorResult &op, + const std::vector &tokens) { + return std::make_unique( + AddressWithOffset{tokens.at(0).getNumericValue(), op.offset1}, + tokens.size() >= 2 ? tokens.at(1).getNumericValue() : 0, + tokens.size() >= 3 ? tokens.at(2).getNumericValue() : 1); + } + + + PushImm::PushImm(const std::vector &value) { instructions.push_back(std::make_unique(Calc::Operation::SUB, 0, stackOffsetRegisterAddress, stackOffsetRegisterAddress, value.size())); @@ -57,6 +129,18 @@ namespace Instruction { } } + std::vector PushImm::toBytes() const { + std::vector v; + for (auto &i : instructions) { + auto b = i->toBytes(); + v.insert(v.end(), b.begin(), b.end()); + } + return v; + } + + + + Push::Push(const AddressWithOffset &address, uint8_t count) { if (count > 4) { throw std::runtime_error("Push address count cannot be larger than 4 words at once"); @@ -76,6 +160,86 @@ namespace Instruction { return v; } + std::unique_ptr Push::fromTokens(const Instruction::Instruction::parseOperatorResult &op, + const std::vector &tokens) { + if (tokens.at(0).getType() == Token::Type::RegisterLocation) { + return std::make_unique( + AddressWithOffset{tokens.at(0).getNumericValue(), op.offset1}, + tokens.size() >= 2 ? tokens.at(1).getNumericValue() : 1); + } else { + std::vector data; + for (auto it = tokens.begin(); it != tokens.end(); ++it) { + data.emplace_back(it->getNumericValue()); + } + return std::make_unique(data); + } + } + + + + PushGroup::PushGroup(const std::vector>>& group) { + std::vector>> totalData; + uint32_t totalElements = 0; + + for(auto& i : group){ + auto& kind = i.first; + if(kind == Kind::Immediate){ + if(totalData.empty() || totalData.back().first != Kind::Immediate){ + totalData.push_back({kind, {i.second.first}}); + }else { + totalData.back().second.emplace_back(i.second.first); + } + ++totalElements; + } else if (kind == Kind::Address){ + totalData.push_back({kind, {i.second.second.address, i.second.second.offset, i.second.first}}); + totalElements += i.second.first; + } + } + + instructions.push_back(std::make_unique(Calc::Operation::SUB, 0, stackOffsetRegisterAddress, + stackOffsetRegisterAddress, totalElements)); + + + uint32_t currentIndex = 0; + for(auto& i : totalData){ + if(i.first == Kind::Immediate){ + auto reversedData = i.second; + std::reverse(reversedData.begin(), reversedData.end()); + + if (i.second.size() > 16) { + instructions.push_back( + std::make_unique(AddressWithOffset{1 + totalElements - currentIndex - (uint32_t) reversedData.size(), stackOffsetRegister}, 1, reversedData)); + } else { + instructions.push_back( + std::make_unique(AddressWithOffset{1 + totalElements - currentIndex - (uint32_t) reversedData.size(), stackOffsetRegister}, reversedData)); + } + currentIndex += i.second.size(); + } else if (i.first == Kind::Address && i.second.size() == 3){ + if (i.second.at(2) > 4) { + throw std::runtime_error("Push address count cannot be larger than 4 words at once"); + } + instructions.push_back(std::make_unique(AddressWithOffset{1 + totalElements - currentIndex - i.second.at(2), stackOffsetRegister}, AddressWithOffset{i.second.at(0), (uint8_t)i.second.at(1)}, i.second.at(2))); + + currentIndex += i.second.at(2); + } + } + } + + std::vector PushGroup::toBytes() const { + std::vector v; + for (auto &i : instructions) { + auto b = i->toBytes(); + v.insert(v.end(), b.begin(), b.end()); + } + return v; + } + + std::unique_ptr PushGroup::fromTokens(const Instruction::Instruction::parseOperatorResult &op, + const std::vector &tokens) { + return nullptr; + } + + PopPeek::PopPeek(const AddressWithOffset &address, uint32_t offset, uint8_t count) { if (count > 4) { throw std::runtime_error("PopPeek count cannot be larger than 4 words at once"); @@ -93,7 +257,6 @@ namespace Instruction { return v; } - std::unique_ptr PopPeek::fromTokens(const Instruction::Instruction::parseOperatorResult &op, const std::vector &tokens) { return std::make_unique( @@ -102,6 +265,11 @@ namespace Instruction { tokens.size() >= 3 ? tokens.at(2).getNumericValue() : 1); } + + + + + PopImm::PopImm(uint8_t count) { instructions.push_back(std::make_unique(Calc::Operation::ADD, 0, stackOffsetRegisterAddress, stackOffsetRegisterAddress, count)); @@ -122,6 +290,10 @@ namespace Instruction { return std::make_unique(tokens.size() >= 1 ? tokens.at(0).getNumericValue() : 1); } + + + + Pop::Pop(const AddressWithOffset &address, uint8_t count) { if (count > 4) { throw std::runtime_error("Pop count cannot be larger than 4 words at once"); @@ -149,20 +321,7 @@ namespace Instruction { tokens.size() >= 2 ? tokens.at(1).getNumericValue() : 1); } - std::unique_ptr Push::fromTokens(const Instruction::Instruction::parseOperatorResult &op, - const std::vector &tokens) { - if (tokens.at(0).getType() == Token::Type::RegisterLocation) { - return std::make_unique( - AddressWithOffset{tokens.at(0).getNumericValue(), op.offset1}, - tokens.size() >= 2 ? tokens.at(1).getNumericValue() : 1); - } else { - std::vector data; - for (auto it = tokens.begin(); it != tokens.end(); ++it) { - data.emplace_back(it->getNumericValue()); - } - return std::make_unique(data); - } - } + } } diff --git a/src/instructions/virtual/Stack.h b/src/instructions/virtual/Stack.h index 5cedbd0..e0f5f1d 100644 --- a/src/instructions/virtual/Stack.h +++ b/src/instructions/virtual/Stack.h @@ -36,11 +36,90 @@ namespace Instruction { static uint32_t stackRegisterStart = (uint32_t)MgmtRegisters::BSM_SCRATCH_END; //Half top portion of BSM_SCRATCH static uint32_t stackRegisterSize = 512; static uint32_t stackRegisterEnd = (uint32_t)MgmtRegisters::BSM_SCRATCH_END - stackRegisterSize; - static uint8_t stackOffsetRegister = 3; //BSM_ADDR_OFFSET to use - static uint32_t stackOffsetRegisterAddress = (uint32_t)MgmtRegisters::BSM_ADDR_OFFSET_0 + stackOffsetRegister; + static uint32_t stackOffsetRegisterAddress = (uint32_t)MgmtRegisters::BSM_ADDR_OFFSET_3; + static uint32_t frameOffsetRegisterAddress = (uint32_t)MgmtRegisters::BSM_ADDR_OFFSET_2; + static uint8_t stackOffsetRegister = stackOffsetRegisterAddress - (uint32_t)MgmtRegisters::BSM_ADDR_OFFSET_0; //BSM_ADDR_OFFSET to use + static uint8_t frameOffsetRegister = frameOffsetRegisterAddress - (uint32_t)MgmtRegisters::BSM_ADDR_OFFSET_0; //BSM_ADDR_OFFSET to use //TODO static uint32_t stackSaveRegister = stackRegisterStart; //Set to where to save stack pointer, otherwise it will be kept on offset register selected and not restore it + + class PutImm : public Instruction { + private: + std::vector> instructions; + public: + + explicit PutImm(uint32_t param, uint32_t value) : PutImm(param, std::vector{value}) { + + } + + explicit PutImm(uint32_t param, const std::vector &value); + + CommandOp getCommand() const override { + return CommandOp::END; + }; + + std::vector toBytes() const override; + + size_t getByteSize() const override{ + size_t s = 0; + for(auto& i : instructions){ + s += i->getByteSize(); + } + return s; + } + }; + + class Put : public Instruction { + private: + std::vector> instructions; + public: + + explicit Put(uint32_t param, const AddressWithOffset &address, uint8_t count = 1); + + CommandOp getCommand() const override { + return CommandOp::END; + }; + + std::vector toBytes() const override; + + size_t getByteSize() const override{ + size_t s = 0; + for(auto& i : instructions){ + s += i->getByteSize(); + } + return s; + } + + static std::unique_ptr + fromTokens(const Instruction::parseOperatorResult &op, const std::vector &tokens); + }; + + class Get : public Instruction { + private: + std::vector> instructions; + public: + + explicit Get(const AddressWithOffset &address, uint32_t param, uint8_t count = 1); + + CommandOp getCommand() const override { + return CommandOp::END; + }; + + std::vector toBytes() const override; + + size_t getByteSize() const override{ + size_t s = 0; + for(auto& i : instructions){ + s += i->getByteSize(); + } + return s; + } + + static std::unique_ptr + fromTokens(const Instruction::parseOperatorResult &op, const std::vector &tokens); + }; + class PushImm : public Instruction { private: std::vector> instructions; @@ -92,6 +171,36 @@ namespace Instruction { fromTokens(const Instruction::parseOperatorResult &op, const std::vector &tokens); }; + class PushGroup : public Instruction { + private: + std::vector> instructions; + public: + + enum class Kind{ + Immediate, + Address + }; + + explicit PushGroup(const std::vector>>&); + + CommandOp getCommand() const override { + return CommandOp::END; + }; + + std::vector toBytes() const override; + + size_t getByteSize() const override{ + size_t s = 0; + for(auto& i : instructions){ + s += i->getByteSize(); + } + return s; + } + + static std::unique_ptr + fromTokens(const Instruction::parseOperatorResult &op, const std::vector &tokens); + }; + class PopPeek : public Instruction { private: std::vector> instructions; diff --git a/src/rrcas.cpp b/src/rrcas.cpp index 4ae5536..b3b6508 100644 --- a/src/rrcas.cpp +++ b/src/rrcas.cpp @@ -41,6 +41,12 @@ int main(int argc, char *argv[]) { linker.addVariable("rrcc_STACK_POINTER", {Token(Token::Type::RegisterLocation, std::to_string(Instruction::Stack::stackOffsetRegisterAddress), Instruction::Stack::stackOffsetRegisterAddress)}); + linker.addVariable("rrcc_FRAME_POINTER", {Token(Token::Type::RegisterLocation, + std::to_string(Instruction::Stack::frameOffsetRegisterAddress), + Instruction::Stack::frameOffsetRegisterAddress)}); + for (uint32_t i = Instruction::Stack::stackRegisterEnd; i <= Instruction::Stack::stackRegisterStart; ++i){ + linker.addReservation(i, "rrc_STACK_RESERVED_" + std::to_string(i)); + } for (auto &r : embeddedResources) { std::vector bytes(r.begin(), r.end());