Major overhaul of Stack system and calling convention, added PUSH, PUT, GET (and immediate versions), optimized FastCall, expanded RET
Some checks reported errors
continuous-integration/drone/push Build was killed

* 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
This commit is contained in:
DataHoarder 2021-08-03 00:02:49 +02:00
parent 8c93edd1f9
commit 835c84c944
8 changed files with 399 additions and 90 deletions

View file

@ -12,22 +12,22 @@
.constant P0 std_PARAMETER_0
.constant P1 std_PARAMETER_1
; These are offset registers to be called with <OP>~3 to access stack parameters
.constant P2 %1, +1 ; Equivalent to same address in POPP <Reg>, 1
.constant P3 %1, +2 ; Equivalent to same address in POPP <Reg>, 2
.constant P4 %1, +3 ; Equivalent to same address in POPP <Reg>, 3
.constant P5 %1, +4 ; Equivalent to same address in POPP <Reg>, 4
.constant P6 %1, +5 ; Equivalent to same address in POPP <Reg>, 5
.constant P7 %1, +6 ; Equivalent to same address in POPP <Reg>, 6
.constant P8 %1, +7 ; Equivalent to same address in POPP <Reg>, 7
.constant P9 %1, +8 ; Equivalent to same address in POPP <Reg>, 8
.constant P10 %1, +9 ; Equivalent to same address in POPP <Reg>, 9
.constant P11 %1, +10 ; Equivalent to same address in POPP <Reg>, 10
.constant P12 %1, +11 ; Equivalent to same address in POPP <Reg>, 11
.constant P13 %1, +12 ; Equivalent to same address in POPP <Reg>, 12
.constant P14 %1, +13 ; Equivalent to same address in POPP <Reg>, 13
.constant P15 %1, +14 ; Equivalent to same address in POPP <Reg>, 14
.constant P16 %1, +15 ; Equivalent to same address in POPP <Reg>, 15
; These are offset registers to be called with <OP>~2 to access stack frame parameters
.constant P2 %0, +1 ; Equivalent to same address in GET <Reg>, 1
.constant P3 %0, +2 ; Equivalent to same address in GET <Reg>, 2
.constant P4 %0, +3 ; Equivalent to same address in GET <Reg>, 3
.constant P5 %0, +4 ; Equivalent to same address in GET <Reg>, 4
.constant P6 %0, +5 ; Equivalent to same address in GET <Reg>, 5
.constant P7 %0, +6 ; Equivalent to same address in GET <Reg>, 6
.constant P8 %0, +7 ; Equivalent to same address in GET <Reg>, 7
.constant P9 %0, +8 ; Equivalent to same address in GET <Reg>, 8
.constant P10 %0, +9 ; Equivalent to same address in GET <Reg>, 9
.constant P11 %0, +10 ; Equivalent to same address in GET <Reg>, 10
.constant P12 %0, +11 ; Equivalent to same address in GET <Reg>, 11
.constant P13 %0, +12 ; Equivalent to same address in GET <Reg>, 12
.constant P14 %0, +13 ; Equivalent to same address in GET <Reg>, 13
.constant P15 %0, +14 ; Equivalent to same address in GET <Reg>, 14
.constant P16 %0, +15 ; Equivalent to same address in GET <Reg>, 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

View file

@ -26,6 +26,7 @@
*****************************************************************************/
#include <sstream>
#include <algorithm>
#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<Token> 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);
}
}

View file

@ -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<Instruction> Ret::fromTokens(const Instruction::Instruction::parseOperatorResult &op,
const std::vector<Token> &tokens) {
if(!tokens.empty()){
const auto& t = tokens.at(0);
if(t.getType() == Token::Type::RegisterLocation){
return std::make_unique<Ret>(AddressWithOffset{t.getNumericValue(), op.offset1});
} else {
return std::make_unique<Ret>(t.getNumericValue());
}
}
return std::make_unique<Ret>();
}
Ret::Ret(const AddressWithOffset &address) {
instructions.push_back(std::make_unique<Copy>(AddressWithOffset{(uint32_t)MgmtRegisters::MGMT_SCRATCH_0, 0}, address, 1));
instructions.push_back(std::make_unique<Stack::PopImm>(1));
instructions.push_back(std::make_unique<Return>(AddressWithOffset{0, Stack::stackOffsetRegister}));
}
Ret::Ret(uint32_t value) {
instructions.push_back(std::make_unique<Write>(AddressWithOffset{(uint32_t)MgmtRegisters::MGMT_SCRATCH_0, 0}, std::vector<uint32_t>({value})));
instructions.push_back(std::make_unique<Stack::PopImm>(1));
instructions.push_back(std::make_unique<Return>(AddressWithOffset{0, Stack::stackOffsetRegister}));
}
Ret::Ret() {
instructions.push_back(std::make_unique<Stack::PopImm>(1));
instructions.push_back(std::make_unique<Return>(AddressWithOffset{0, Stack::stackOffsetRegister}));

View file

@ -49,7 +49,7 @@ namespace Instruction {
std::vector<uint8_t> 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;

View file

@ -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<Token> &data) {
if(data.size() > 2){
instructions.push_back(std::make_unique<Stack::PopImm>(data.size() - 2));
}
instructions.push_back(std::make_unique<Copy>(AddressWithOffset{Stack::frameOffsetRegisterAddress, 0}, AddressWithOffset{1, Stack::stackOffsetRegister}, 1));
instructions.push_back(std::make_unique<Stack::PopImm>(1 + (data.size() > 2 ? data.size() - 2 : 0)));
}
void FastCall::initData(const std::vector<Token> &data) {
bool isAllData = true;
std::vector<std::pair<Stack::PushGroup::Kind, std::pair<uint32_t, AddressWithOffset>>> 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<Copy>(AddressWithOffset{(uint32_t)MgmtRegisters::MGMT_SCRATCH_0 + offset, 0}, AddressWithOffset{t.getNumericValue(), 0}, 1)); //TODO: allow offsets
}else{
instructions.push_back(std::make_unique<Write>(AddressWithOffset{(uint32_t)MgmtRegisters::MGMT_SCRATCH_0 + offset, 0}, std::vector<uint32_t>{t.getNumericValue()}));
}
}
++offset;
}
if(isAllData){
std::vector<uint32_t> scratchData;
std::vector<uint32_t> 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<Write>(AddressWithOffset{(uint32_t)MgmtRegisters::MGMT_SCRATCH_0, 0}, scratchData));
if(!stackData.empty()){
instructions.push_back(std::make_unique<Stack::PushImm>(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<Copy>(AddressWithOffset{(uint32_t)MgmtRegisters::MGMT_SCRATCH_0 + offset, 0}, AddressWithOffset{t.getNumericValue(), 0}, 1)); //TODO: allow offsets
}else{
instructions.push_back(std::make_unique<Write>(AddressWithOffset{(uint32_t)MgmtRegisters::MGMT_SCRATCH_0 + offset, 0}, std::vector<uint32_t>{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<Stack::Push>(AddressWithOffset{t.getNumericValue(), 0})); //TODO: allow offsets
}else{
instructions.push_back(std::make_unique<Stack::PushImm>(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<Stack::Push>(AddressWithOffset{t.getNumericValue(), 0})); //TODO: allow offsets
}else{
instructions.push_back(std::make_unique<Stack::PushImm>(t.getNumericValue()));
}
}
*/
}
groupData.push_back({Stack::PushGroup::Kind::Address, {1, AddressWithOffset{Stack::frameOffsetRegisterAddress, 0}}});
instructions.push_back(std::make_unique<Stack::PushGroup>(groupData));
//instructions.push_back(std::make_unique<Stack::Push>(AddressWithOffset{Stack::frameOffsetRegisterAddress, 0}));
instructions.push_back(std::make_unique<CalcImm>(Calc::Operation::SUB, 0, Stack::frameOffsetRegisterAddress, Stack::stackOffsetRegisterAddress, 1));
}
std::unique_ptr<Instruction> FastCall::fromTokens(const Instruction::parseOperatorResult &op, const std::vector<Token> &tokens) {

View file

@ -27,6 +27,7 @@
#include <stdexcept>
#include <algorithm>
#include "Stack.h"
#include "../Write.h"
#include "../Load.h"
@ -36,7 +37,18 @@
namespace Instruction {
namespace Stack {
std::vector<uint8_t> PushImm::toBytes() const {
PutImm::PutImm(uint32_t param, const std::vector<uint32_t> &value) {
if (value.size() > 16) {
instructions.push_back(
std::make_unique<Load>(AddressWithOffset{param, frameOffsetRegister}, 1, value));
} else {
instructions.push_back(
std::make_unique<Write>(AddressWithOffset{param, frameOffsetRegister}, value));
}
}
std::vector<uint8_t> PutImm::toBytes() const {
std::vector<uint8_t> 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<Copy>(AddressWithOffset{param, frameOffsetRegister}, address, count));
}
std::vector<uint8_t> Put::toBytes() const {
std::vector<uint8_t> v;
for (auto &i : instructions) {
auto b = i->toBytes();
v.insert(v.end(), b.begin(), b.end());
}
return v;
}
std::unique_ptr<Instruction> Put::fromTokens(const Instruction::Instruction::parseOperatorResult &op,
const std::vector<Token> &tokens) {
if (tokens.at(0).getType() == Token::Type::RegisterLocation) {
return std::make_unique<Stack::Put>(tokens.at(0).getNumericValue(), AddressWithOffset{tokens.at(1).getNumericValue(), op.offset1}, tokens.size() >= 3 ? tokens.at(2).getNumericValue() : 1);
} else {
std::vector<uint32_t> data;
for (auto it = tokens.begin() + 1; it != tokens.end(); ++it) {
data.emplace_back(it->getNumericValue());
}
return std::make_unique<Stack::PutImm>(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<Copy>(address, AddressWithOffset{param, frameOffsetRegister}, count));
}
std::vector<uint8_t> Get::toBytes() const {
std::vector<uint8_t> v;
for (auto &i : instructions) {
auto b = i->toBytes();
v.insert(v.end(), b.begin(), b.end());
}
return v;
}
std::unique_ptr<Instruction> Get::fromTokens(const Instruction::Instruction::parseOperatorResult &op,
const std::vector<Token> &tokens) {
return std::make_unique<Stack::Get>(
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<uint32_t> &value) {
instructions.push_back(std::make_unique<CalcImm>(Calc::Operation::SUB, 0, stackOffsetRegisterAddress,
stackOffsetRegisterAddress, value.size()));
@ -57,6 +129,18 @@ namespace Instruction {
}
}
std::vector<uint8_t> PushImm::toBytes() const {
std::vector<uint8_t> 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<Instruction> Push::fromTokens(const Instruction::Instruction::parseOperatorResult &op,
const std::vector<Token> &tokens) {
if (tokens.at(0).getType() == Token::Type::RegisterLocation) {
return std::make_unique<Stack::Push>(
AddressWithOffset{tokens.at(0).getNumericValue(), op.offset1},
tokens.size() >= 2 ? tokens.at(1).getNumericValue() : 1);
} else {
std::vector<uint32_t> data;
for (auto it = tokens.begin(); it != tokens.end(); ++it) {
data.emplace_back(it->getNumericValue());
}
return std::make_unique<Stack::PushImm>(data);
}
}
PushGroup::PushGroup(const std::vector<std::pair<Kind, std::pair<uint32_t, AddressWithOffset>>>& group) {
std::vector<std::pair<Kind, std::vector<uint32_t>>> 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<CalcImm>(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<Load>(AddressWithOffset{1 + totalElements - currentIndex - (uint32_t) reversedData.size(), stackOffsetRegister}, 1, reversedData));
} else {
instructions.push_back(
std::make_unique<Write>(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<Copy>(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<uint8_t> PushGroup::toBytes() const {
std::vector<uint8_t> v;
for (auto &i : instructions) {
auto b = i->toBytes();
v.insert(v.end(), b.begin(), b.end());
}
return v;
}
std::unique_ptr<Instruction> PushGroup::fromTokens(const Instruction::Instruction::parseOperatorResult &op,
const std::vector<Token> &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<Instruction> PopPeek::fromTokens(const Instruction::Instruction::parseOperatorResult &op,
const std::vector<Token> &tokens) {
return std::make_unique<Stack::PopPeek>(
@ -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<CalcImm>(Calc::Operation::ADD, 0, stackOffsetRegisterAddress,
stackOffsetRegisterAddress, count));
@ -122,6 +290,10 @@ namespace Instruction {
return std::make_unique<Stack::PopImm>(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<Instruction> Push::fromTokens(const Instruction::Instruction::parseOperatorResult &op,
const std::vector<Token> &tokens) {
if (tokens.at(0).getType() == Token::Type::RegisterLocation) {
return std::make_unique<Stack::Push>(
AddressWithOffset{tokens.at(0).getNumericValue(), op.offset1},
tokens.size() >= 2 ? tokens.at(1).getNumericValue() : 1);
} else {
std::vector<uint32_t> data;
for (auto it = tokens.begin(); it != tokens.end(); ++it) {
data.emplace_back(it->getNumericValue());
}
return std::make_unique<Stack::PushImm>(data);
}
}
}
}

View file

@ -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<std::unique_ptr<Instruction>> instructions;
public:
explicit PutImm(uint32_t param, uint32_t value) : PutImm(param, std::vector<uint32_t>{value}) {
}
explicit PutImm(uint32_t param, const std::vector<uint32_t> &value);
CommandOp getCommand() const override {
return CommandOp::END;
};
std::vector<uint8_t> 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<std::unique_ptr<Instruction>> instructions;
public:
explicit Put(uint32_t param, const AddressWithOffset &address, uint8_t count = 1);
CommandOp getCommand() const override {
return CommandOp::END;
};
std::vector<uint8_t> 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<Instruction>
fromTokens(const Instruction::parseOperatorResult &op, const std::vector<Token> &tokens);
};
class Get : public Instruction {
private:
std::vector<std::unique_ptr<Instruction>> instructions;
public:
explicit Get(const AddressWithOffset &address, uint32_t param, uint8_t count = 1);
CommandOp getCommand() const override {
return CommandOp::END;
};
std::vector<uint8_t> 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<Instruction>
fromTokens(const Instruction::parseOperatorResult &op, const std::vector<Token> &tokens);
};
class PushImm : public Instruction {
private:
std::vector<std::unique_ptr<Instruction>> instructions;
@ -92,6 +171,36 @@ namespace Instruction {
fromTokens(const Instruction::parseOperatorResult &op, const std::vector<Token> &tokens);
};
class PushGroup : public Instruction {
private:
std::vector<std::unique_ptr<Instruction>> instructions;
public:
enum class Kind{
Immediate,
Address
};
explicit PushGroup(const std::vector<std::pair<Kind, std::pair<uint32_t, AddressWithOffset>>>&);
CommandOp getCommand() const override {
return CommandOp::END;
};
std::vector<uint8_t> 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<Instruction>
fromTokens(const Instruction::parseOperatorResult &op, const std::vector<Token> &tokens);
};
class PopPeek : public Instruction {
private:
std::vector<std::unique_ptr<Instruction>> instructions;

View file

@ -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<uint8_t> bytes(r.begin(), r.end());