Flip stack around to be similar to other architectures. Implement FASTCALL calling convention
All checks were successful
continuous-integration/drone/push Build is passing

This commit is contained in:
DataHoarder 2021-01-02 10:30:32 +01:00
parent bb8df3aae2
commit 8514bb8a90
28 changed files with 314 additions and 37 deletions

View file

@ -44,12 +44,16 @@ set(SOURCE_FILES
src/instructions/virtual/Stack.cpp src/instructions/virtual/Stack.h
src/instructions/virtual/Call.cpp src/instructions/virtual/Call.h
src/instructions/virtual/FastCall.cpp src/instructions/virtual/FastCall.h
src/Parser.cpp src/Parser.h
src/Token.cpp src/Token.h
src/Declaration.cpp src/Declaration.h
src/Function.cpp src/Function.h
src/Assembler.cpp src/Assembler.h src/Linker.cpp src/Linker.h src/EmbeddedResource.h src/BaseRegisters.h)
src/Assembler.cpp src/Assembler.h
src/Linker.cpp src/Linker.h
src/EmbeddedResource.h src/BaseRegisters.h
)
ADD_RESOURCES(embeddedResources
asm/registers.asm

View file

@ -3,6 +3,6 @@
.constant rrcc_ENTRYPOINT @__init
__init:
MOV rrcc_STACK_POINTER, 0 ; Reset Stack pointer to 0
CALL @entrypoint ; Calls user-defined entrypoint
END ; Stops execution if it ever returns
MOV rrcc_STACK_POINTER, rrcc_STACK_START_IMM ; Reset Stack pointer to its starting position
CALL @entrypoint ; Calls user-defined entrypoint
END ; Stops execution if it ever returns

View file

@ -1,7 +1,14 @@
; Standard Library
.constant std_RETURN_VALUE MGMT_SCRATCH_0
.constant RRET std_RETURN_VALUE ;Alias
; These registers are used when passing the first two parameters to a function via FastCall
.constant std_PARAMETER_0 MGMT_SCRATCH_0
.constant std_PARAMETER_1 MGMT_SCRATCH_1
; Also used as single return value
.constant std_RETURN_VALUE MGMT_SCRATCH_0
.constant RRET std_RETURN_VALUE ;Alias
.constant P0 std_PARAMETER_0
.constant P1 std_PARAMETER_1
; 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.
@ -39,22 +46,19 @@
.constant RE std_EPHEMERAL_REGISTER_E
.constant RF std_EPHEMERAL_REGISTER_F
; uint std_multiply(uint A, uint B). Return value on RRET
; FASTCALL uint std_multiply(uint A, uint B). Return value on RRET
; Uses simple addition
; TODO: use add + shift
.constant std_mul @std_multiply
.constant std_multiply @std_multiply
std_multiply:
PUSH R0 ; Save old value of R0
PUSH BSM_COUNTER_0 ; Save old value of counter
POPP R0, 3 ; Get B
POPP BSM_COUNTER_0, 4 ; Get A
MOV BSM_COUNTER_0, P0 ; Move A to counter
MOV RRET, 0
JUMP @.loop ; Skip first iteration
.multiply:
ADD RRET, RRET, R0 ; Add B to itself A times
ADD RRET, RRET, P1 ; Add B to itself A times
.loop: LOOP @.multiply ; Check if 0, if not, decrease A and go back. Use COUNTER[0]
POP BSM_COUNTER_0 ; Restore old value of counter
POP R0 ; Restore old value of R0
RET 2 ; Return and get rid of 2 parameters
RET ; Return, no need to get rid of stack as fastcall passed them on registers

View file

@ -143,8 +143,7 @@ uint32_t Assembler::placeFunction(uint32_t base, const Function &function) {
instr->setAddress(offset);
auto b = instr->toBytes();
offset += b.size();
offset += instr->getByteSize();
endAddresses[instr->getAddress()] = offset;
}
@ -183,11 +182,11 @@ uint32_t Assembler::placeFunction(uint32_t base, const Function &function) {
instr->setAddress(offset);
instr->setEndAddress(endAddresses[offset]);
instr->setEndAddress(endAddresses[offset]); //TODO: this might not be needed anymore!
auto data = instr->toBytes();
if (offset + data.size() > +bytes.size()) {
if (offset + data.size() > bytes.size()) {
throw std::runtime_error("Instruction encoding exceeds image size");
}

View file

@ -33,6 +33,7 @@ enum class MgmtRegisters {
MGMT_SCRATCH_1 = 0x9,
BSM_SCRATCH_START = 0x800,
BSM_SCRATCH_END = 0xBFF,
BSM_ADDR_OFFSET_0 = 0xC04,
BSM_ADDR_OFFSET_1 = BSM_ADDR_OFFSET_0 + 1,

View file

@ -46,6 +46,10 @@ namespace Instruction {
std::vector<uint8_t> toBytes() const override;
size_t getByteSize() const override{
return 4 * 4;
}
static std::unique_ptr<Instruction>
fromEqualTokens(const Instruction::parseOperatorResult &op, const std::vector<Token> &tokens);

View file

@ -60,6 +60,10 @@ namespace Instruction {
std::vector<uint8_t> toBytes() const override;
size_t getByteSize() const override{
return 4 * 3;
}
Operation operation;
uint8_t addressOffset;

View file

@ -49,6 +49,10 @@ namespace Instruction {
std::vector<uint8_t> toBytes() const override;
size_t getByteSize() const override{
return 4 * 3;
}
static std::unique_ptr<Instruction>
fromAndTokens(const Instruction::parseOperatorResult &op, const std::vector<Token> &tokens);

View file

@ -36,7 +36,7 @@ namespace Instruction {
}
Copy(const AddressWithOffset &to, const AddressWithOffset &from, uint8_t count) : count(count),
Copy(const AddressWithOffset &to, const AddressWithOffset &from, uint8_t count = 1) : count(count),
addressAA(
from),
addressBB(
@ -49,6 +49,10 @@ namespace Instruction {
std::vector<uint8_t> toBytes() const override;
size_t getByteSize() const override{
return 4 * 2;
}
static std::unique_ptr<Instruction>
fromTokens(const Instruction::parseOperatorResult &op, const std::vector<Token> &tokens);

View file

@ -43,6 +43,10 @@ namespace Instruction {
std::vector<uint8_t> toBytes() const override;
size_t getByteSize() const override{
return 4;
}
static std::unique_ptr<Instruction>
fromTokens(const Instruction::parseOperatorResult &op, const std::vector<Token> &tokens);

View file

@ -47,6 +47,10 @@ namespace Instruction {
std::vector<uint8_t> toBytes() const override;
size_t getByteSize() const override{
return 4 * 4;
}
static std::unique_ptr<Instruction>
fromTokens(const Instruction::parseOperatorResult &op, const std::vector<Token> &tokens);

View file

@ -45,6 +45,7 @@
#include "virtual/Stack.h"
#include "virtual/Call.h"
#include "virtual/FastCall.h"
#include "../Declaration.h"
@ -60,6 +61,7 @@ namespace Instruction {
addOperator("CALL", 1, Call::fromTokens);
addOperator("RET", 0, Ret::fromTokens);
addOperator("FASTCALL", 1, FastCall::fromTokens);
addOperator("MOV", 2, [](const parseOperatorResult &op, const std::vector<Token> &tokens) -> std::unique_ptr<Instruction> {
if (tokens.at(1).getType() == Token::Type::RegisterLocation) {

View file

@ -77,6 +77,8 @@ namespace Instruction {
virtual std::vector<uint8_t> toBytes() const = 0;
virtual size_t getByteSize() const = 0;
virtual CommandOp getCommand() const = 0;
void setAddress(uint32_t address){

View file

@ -45,6 +45,10 @@ namespace Instruction {
std::vector<uint8_t> toBytes() const override;
size_t getByteSize() const override{
return 4;
}
static std::unique_ptr<Instruction>
fromTokens(const Instruction::parseOperatorResult &op, const std::vector<Token> &tokens);

View file

@ -50,6 +50,10 @@ namespace Instruction {
std::vector<uint8_t> toBytes() const override;
size_t getByteSize() const override{
return 4 * 2 + data.size() * 4;
}
static std::unique_ptr<Instruction>
fromTokens(const Instruction::parseOperatorResult &op, const std::vector<Token> &tokens);

View file

@ -45,6 +45,10 @@ namespace Instruction {
std::vector<uint8_t> toBytes() const override;
size_t getByteSize() const override{
return 4;
}
static std::unique_ptr<Instruction>
fromTokens(const Instruction::parseOperatorResult &op, const std::vector<Token> &tokens);

View file

@ -49,6 +49,10 @@ namespace Instruction {
std::vector<uint8_t> toBytes() const override;
size_t getByteSize() const override{
return 4 * 5;
}
static std::unique_ptr<Instruction>
fromEqualTokens(const Instruction::parseOperatorResult &op, const std::vector<Token> &tokens);

View file

@ -45,6 +45,10 @@ namespace Instruction {
std::vector<uint8_t> toBytes() const override;
size_t getByteSize() const override{
return 4;
}
static std::unique_ptr<Instruction>
fromTokens(const Instruction::parseOperatorResult &op, const std::vector<Token> &tokens);

View file

@ -46,6 +46,10 @@ namespace Instruction {
std::vector<uint8_t> toBytes() const override;
size_t getByteSize() const override{
return 4 * 3;
}
static std::unique_ptr<Instruction>
fromTokens(const Instruction::parseOperatorResult &op, const std::vector<Token> &tokens);

View file

@ -47,6 +47,10 @@ namespace Instruction {
std::vector<uint8_t> toBytes() const override;
size_t getByteSize() const override{
return 4;
}
static std::unique_ptr<Instruction>
fromTokens(const Instruction::parseOperatorResult &op, const std::vector<Token> &tokens);

View file

@ -47,6 +47,10 @@ namespace Instruction {
std::vector<uint8_t> toBytes() const override;
size_t getByteSize() const override{
return 4 + data.size() * 4;
}
static std::unique_ptr<Instruction>
fromTokens(const Instruction::parseOperatorResult &op, const std::vector<Token> &tokens);

View file

@ -34,7 +34,7 @@
namespace Instruction {
std::vector<uint8_t> Call::toBytes() const {
std::vector<uint8_t> v = Stack::PushImm(getEndAddress()).toBytes();
std::vector<uint8_t> v = Stack::PushImm(getAddress() + getByteSize()).toBytes();
if(address == 0){
auto b = (Return(addressWithOffset)).toBytes();
@ -82,8 +82,8 @@ namespace Instruction {
}
Ret::Ret(uint32_t count) {
instructions.push_back(std::make_unique<Stack::PopImm>(count));
instructions.push_back(std::make_unique<Return>(AddressWithOffset{Stack::stackRegisterStart + count - 1, Stack::stackOffsetRegister}));
instructions.push_back(std::make_unique<Stack::PopImm>(count + 1));
instructions.push_back(std::make_unique<Return>(AddressWithOffset{count, Stack::stackOffsetRegister}));
}
}

View file

@ -48,6 +48,11 @@ namespace Instruction {
std::vector<uint8_t> toBytes() const override;
size_t getByteSize() const override{
//TODO: do not hardcode this
return 4 + 8 + 12; //4 bytes for Return/Jump + 8 bytes for Write + 12 for CalcImm
}
static std::unique_ptr<Instruction> fromTokens(const Instruction::parseOperatorResult &op, const std::vector<Token> &tokens);
};
class Ret : public Instruction {
@ -55,7 +60,7 @@ namespace Instruction {
std::vector<std::unique_ptr<Instruction>> instructions;
public:
explicit Ret(uint32_t count = 1);
explicit Ret(uint32_t count = 0);
CommandOp getCommand() const override {
return CommandOp::END;
@ -63,6 +68,14 @@ namespace Instruction {
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);
};

View file

@ -0,0 +1,93 @@
/*****************************************************************************
* Copyright (c) 2020, rrcc FM10K-Documentation Contributors
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* * Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* * Neither the name of the copyright holder nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*****************************************************************************/
#include "FastCall.h"
#include "Stack.h"
#include "Call.h"
#include "../Copy.h"
#include "../Write.h"
namespace Instruction{
std::vector<uint8_t> FastCall::toBytes() const {
std::vector<uint8_t> v;
for (auto &i : instructions) {
i->setAddress(getAddress() + v.size());
auto b = i->toBytes();
v.insert(v.end(), b.begin(), b.end());
}
return v;
}
FastCall::FastCall(uint32_t address, const std::vector<Token> &data) {
initData(data);
instructions.push_back(std::make_unique<Call>(address));
}
FastCall::FastCall(const AddressWithOffset &address, const std::vector<Token> &data) {
initData(data);
instructions.push_back(std::make_unique<Call>(address));
}
void FastCall::initData(const std::vector<Token> &data) {
uint32_t offset = 0;
for(auto& t : data){
//TODO: optimize for immediate values
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()));
}
}
}
}
std::unique_ptr<Instruction> FastCall::fromTokens(const Instruction::parseOperatorResult &op, const std::vector<Token> &tokens) {
if (tokens.at(0).getType() == Token::Type::CodeLocation || tokens.at(0).getType() == Token::Type::CodeLabel) {
return std::make_unique<FastCall>(tokens.at(0).getNumericValue(), std::vector<Token>(tokens.begin() + 1, tokens.end()));
} else {
return std::make_unique<FastCall>(AddressWithOffset{tokens.at(0).getNumericValue(), op.offset1}, std::vector<Token>(tokens.begin() + 1, tokens.end()));
}
}
}

View file

@ -0,0 +1,59 @@
/*****************************************************************************
* Copyright (c) 2020, rrcc FM10K-Documentation Contributors
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* * Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* * Neither the name of the copyright holder nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*****************************************************************************/
#pragma once
#include "../Instruction.h"
namespace Instruction {
//Akin to __fastcall
class FastCall : public Instruction {
private:
std::vector<std::unique_ptr<Instruction>> instructions;
void initData(const std::vector<Token>& data);
public:
explicit FastCall(const AddressWithOffset& address, const std::vector<Token>& data);
explicit FastCall(uint32_t address, const std::vector<Token>& data);
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);
};
}

View file

@ -46,27 +46,25 @@ namespace Instruction {
}
PushImm::PushImm(const std::vector<uint32_t> &value) {
//TODO: implement stackSaveRegister
instructions.push_back(std::make_unique<CalcImm>(Calc::Operation::SUB, 0, stackOffsetRegisterAddress,
stackOffsetRegisterAddress, value.size()));
if (value.size() > 16) {
instructions.push_back(
std::make_unique<Load>(AddressWithOffset{stackRegisterStart, stackOffsetRegister}, 1, value));
std::make_unique<Load>(AddressWithOffset{1, stackOffsetRegister}, 1, value));
} else {
instructions.push_back(
std::make_unique<Write>(AddressWithOffset{stackRegisterStart, stackOffsetRegister}, value));
std::make_unique<Write>(AddressWithOffset{1, stackOffsetRegister}, value));
}
instructions.push_back(std::make_unique<CalcImm>(Calc::Operation::ADD, 0, stackOffsetRegisterAddress,
stackOffsetRegisterAddress, value.size()));
}
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");
}
//TODO: implement stackSaveRegister
instructions.push_back(
std::make_unique<Copy>(AddressWithOffset{stackRegisterStart, stackOffsetRegister}, address, count));
instructions.push_back(std::make_unique<CalcImm>(Calc::Operation::ADD, 0, stackOffsetRegisterAddress,
instructions.push_back(std::make_unique<CalcImm>(Calc::Operation::SUB, 0, stackOffsetRegisterAddress,
stackOffsetRegisterAddress, count));
instructions.push_back(
std::make_unique<Copy>(AddressWithOffset{1, stackOffsetRegister}, address, count));
}
std::vector<uint8_t> Push::toBytes() const {
@ -83,7 +81,7 @@ namespace Instruction {
throw std::runtime_error("PopPeek count cannot be larger than 4 words at once");
}
instructions.push_back(
std::make_unique<Copy>(address, AddressWithOffset{stackRegisterStart - count - offset, stackOffsetRegister}, count));
std::make_unique<Copy>(address, AddressWithOffset{count + offset, stackOffsetRegister}, count));
}
std::vector<uint8_t> PopPeek::toBytes() const {
@ -105,7 +103,7 @@ namespace Instruction {
}
PopImm::PopImm(uint8_t count) {
instructions.push_back(std::make_unique<CalcImm>(Calc::Operation::SUB, 0, stackOffsetRegisterAddress,
instructions.push_back(std::make_unique<CalcImm>(Calc::Operation::ADD, 0, stackOffsetRegisterAddress,
stackOffsetRegisterAddress, count));
}
@ -128,10 +126,10 @@ namespace Instruction {
if (count > 4) {
throw std::runtime_error("Pop count cannot be larger than 4 words at once");
}
instructions.push_back(std::make_unique<CalcImm>(Calc::Operation::SUB, 0, stackOffsetRegisterAddress,
stackOffsetRegisterAddress, count));
instructions.push_back(
std::make_unique<Copy>(address, AddressWithOffset{stackRegisterStart, stackOffsetRegister}, count));
std::make_unique<Copy>(address, AddressWithOffset{1, stackOffsetRegister}, count));
instructions.push_back(std::make_unique<CalcImm>(Calc::Operation::ADD, 0, stackOffsetRegisterAddress,
stackOffsetRegisterAddress, count));
}
std::vector<uint8_t> Pop::toBytes() const {

View file

@ -32,7 +32,10 @@
namespace Instruction {
namespace Stack {
static uint32_t stackRegisterStart = (uint32_t)MgmtRegisters::BSM_SCRATCH_START + 512; //Half top portion of BSM_SCRATCH
//Stack now grows down
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;
//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
@ -54,6 +57,14 @@ namespace Instruction {
};
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 Push : public Instruction {
@ -69,6 +80,14 @@ namespace Instruction {
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);
};
@ -86,6 +105,14 @@ namespace Instruction {
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);
};
@ -103,6 +130,14 @@ namespace Instruction {
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);
};
@ -120,6 +155,14 @@ namespace Instruction {
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);
};

View file

@ -28,6 +28,9 @@ int main(int argc, char *argv[]) {
linker.addVariable("rrcc_STACK_START",
{Token(Token::Type::RegisterLocation, std::to_string(Instruction::Stack::stackRegisterStart),
Instruction::Stack::stackRegisterStart)});
linker.addVariable("rrcc_STACK_START_IMM",
{Token(Token::Type::Immediate, std::to_string(Instruction::Stack::stackRegisterStart),
Instruction::Stack::stackRegisterStart)});
linker.addVariable("rrcc_STACK_POINTER", {Token(Token::Type::RegisterLocation,
std::to_string(Instruction::Stack::stackOffsetRegisterAddress),
Instruction::Stack::stackOffsetRegisterAddress)});