Flip stack around to be similar to other architectures. Implement FASTCALL calling convention
All checks were successful
continuous-integration/drone/push Build is passing
All checks were successful
continuous-integration/drone/push Build is passing
This commit is contained in:
parent
bb8df3aae2
commit
8514bb8a90
|
@ -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
|
||||
|
|
|
@ -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
|
|
@ -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
|
||||
|
||||
|
|
|
@ -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");
|
||||
}
|
||||
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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);
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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);
|
||||
|
||||
|
|
|
@ -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);
|
||||
|
||||
|
|
|
@ -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);
|
||||
|
||||
|
|
|
@ -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);
|
||||
|
||||
|
|
|
@ -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) {
|
||||
|
|
|
@ -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){
|
||||
|
|
|
@ -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);
|
||||
|
||||
|
|
|
@ -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);
|
||||
|
||||
|
|
|
@ -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);
|
||||
|
||||
|
|
|
@ -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);
|
||||
|
||||
|
|
|
@ -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);
|
||||
|
||||
|
|
|
@ -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);
|
||||
|
||||
|
|
|
@ -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);
|
||||
|
||||
|
|
|
@ -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);
|
||||
|
||||
|
|
|
@ -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}));
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
};
|
||||
|
||||
|
|
93
src/instructions/virtual/FastCall.cpp
Normal file
93
src/instructions/virtual/FastCall.cpp
Normal 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()));
|
||||
}
|
||||
}
|
||||
}
|
59
src/instructions/virtual/FastCall.h
Normal file
59
src/instructions/virtual/FastCall.h
Normal 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);
|
||||
};
|
||||
}
|
|
@ -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 {
|
||||
|
|
|
@ -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);
|
||||
};
|
||||
|
|
|
@ -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)});
|
||||
|
|
Loading…
Reference in a new issue