Compare commits

...

7 commits

Author SHA1 Message Date
DataHoarder c4a98361b1 Implement XOR (without offsets)
Some checks reported errors
continuous-integration/drone/push Build was killed
2021-08-03 17:54:27 +02:00
DataHoarder 6d8b3f0e09 Implement NOP with offsets 2021-08-03 17:54:13 +02:00
DataHoarder 98e3e77686 add comments as base of Instruction 2021-08-03 17:53:44 +02:00
DataHoarder 1cce604661 remove PushGroup::fromTokens 2021-08-03 17:53:02 +02:00
DataHoarder ee8c4ed7de add shorthand for scratch registers 2021-08-03 17:52:42 +02:00
DataHoarder 7ffaa962a3 Added Container virtual instruction 2021-08-03 16:43:24 +02:00
DataHoarder f7b4fa92db stdlib/register API change, use different RRET/RRET_X and P0/P1 2021-08-03 16:10:51 +02:00
11 changed files with 179 additions and 44 deletions

View file

@ -45,6 +45,7 @@ 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/instructions/virtual/Container.h
src/Parser.cpp src/Parser.h
src/Token.cpp src/Token.h

View file

@ -1,16 +1,22 @@
;; Standard Library
;; 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
;; These registers are used within virtual functions as temporary holders
.constant std_SCRATCH_0 MGMT_SCRATCH_0
.constant std_SCRATCH_1 MGMT_SCRATCH_1
;; Also used as single return value
.constant std_RETURN_VALUE MGMT_SCRATCH_0
.constant std_RETURN_VALUE_EXTRA MGMT_SCRATCH_1
.reserve std_RETURN_VALUE 0x1E0
.reserve std_RETURN_VALUE_EXTRA 0x1E1
.reserve std_PARAMETER_0 0x1E2
.reserve std_PARAMETER_1 0x1E3
.constant RRET std_RETURN_VALUE ;;Alias
.constant RRET_X std_RETURN_VALUE_EXTRA ;;Alias
.constant P0 std_PARAMETER_0
.constant P1 std_PARAMETER_1
.constant S0 std_SCRATCH_0
.constant S1 std_SCRATCH_1
;; 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
@ -48,22 +54,22 @@
;; 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.
.constant std_EPHEMERAL_REGISTER_0 BSM_SCRATCH_START +0x1F0
.constant std_EPHEMERAL_REGISTER_1 std_EPHEMERAL_REGISTER_0 +0x1
.constant std_EPHEMERAL_REGISTER_2 std_EPHEMERAL_REGISTER_0 +0x2
.constant std_EPHEMERAL_REGISTER_3 std_EPHEMERAL_REGISTER_0 +0x3
.constant std_EPHEMERAL_REGISTER_4 std_EPHEMERAL_REGISTER_0 +0x4
.constant std_EPHEMERAL_REGISTER_5 std_EPHEMERAL_REGISTER_0 +0x5
.constant std_EPHEMERAL_REGISTER_6 std_EPHEMERAL_REGISTER_0 +0x6
.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_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
.reserve std_EPHEMERAL_REGISTER_0 0x1F0
.constant std_EPHEMERAL_REGISTER_1 0x1F1
.reserve std_EPHEMERAL_REGISTER_2 0x1F2
.reserve std_EPHEMERAL_REGISTER_3 0x1F3
.reserve std_EPHEMERAL_REGISTER_4 0x1F4
.reserve std_EPHEMERAL_REGISTER_5 0x1F5
.reserve std_EPHEMERAL_REGISTER_6 0x1F6
.reserve std_EPHEMERAL_REGISTER_7 0x1F7
.reserve std_EPHEMERAL_REGISTER_8 0x1F8
.reserve std_EPHEMERAL_REGISTER_9 0x1F9
.reserve std_EPHEMERAL_REGISTER_10 0x1FA
.reserve std_EPHEMERAL_REGISTER_11 0x1FB
.reserve std_EPHEMERAL_REGISTER_12 0x1FC
.reserve std_EPHEMERAL_REGISTER_13 0x1FD
.reserve std_EPHEMERAL_REGISTER_14 0x1FE
.reserve std_EPHEMERAL_REGISTER_15 0x1FF
;; Abbreviations
.constant R0 std_EPHEMERAL_REGISTER_0
.constant R1 std_EPHEMERAL_REGISTER_1

View file

@ -29,7 +29,7 @@
enum class MgmtRegisters {
MGMT_SCRATCH_0 = 0x8, //RRET
MGMT_SCRATCH_0 = 0x8,
MGMT_SCRATCH_1 = 0x9,
SRAM_ERR_IM_0 = 0x448,
@ -49,4 +49,30 @@ enum class MgmtRegisters {
INTERNAL_REGISTER_ALWAYS_00000000 = BSM_ADDR_OFFSET_0, //Read only, set at 0
INTERNAL_REGISTER_ALWAYS_FFFFFFFF = SRAM_ERR_IM_0, //SRAM_ERR_IM_0 is default two x with 48 1b bits. RW but it's not changed by default. Alternatively SW_IM is also set to 0xFFFFFFFF
std_SCRATCH_0 = MGMT_SCRATCH_0,
std_SCRATCH_1 = MGMT_SCRATCH_1,
std_RETURN_VALUE = BSM_SCRATCH_START + 0x1E0,
std_RETURN_VALUE_EXTRA = BSM_SCRATCH_START + 0x1E1,
std_PARAMETER_0 = BSM_SCRATCH_START + 0x1E2,
std_PARAMETER_1 = BSM_SCRATCH_START + 0x1E3,
std_EPHEMERAL_REGISTER_0 = BSM_SCRATCH_START + 0x1F0,
std_EPHEMERAL_REGISTER_1 = std_EPHEMERAL_REGISTER_0 + 0x1,
std_EPHEMERAL_REGISTER_2 = std_EPHEMERAL_REGISTER_0 + 0x2,
std_EPHEMERAL_REGISTER_3 = std_EPHEMERAL_REGISTER_0 + 0x3,
std_EPHEMERAL_REGISTER_4 = std_EPHEMERAL_REGISTER_0 + 0x4,
std_EPHEMERAL_REGISTER_5 = std_EPHEMERAL_REGISTER_0 + 0x5,
std_EPHEMERAL_REGISTER_6 = std_EPHEMERAL_REGISTER_0 + 0x6,
std_EPHEMERAL_REGISTER_7 = std_EPHEMERAL_REGISTER_0 + 0x7,
std_EPHEMERAL_REGISTER_8 = std_EPHEMERAL_REGISTER_0 + 0x8,
std_EPHEMERAL_REGISTER_9 = std_EPHEMERAL_REGISTER_0 + 0x9,
std_EPHEMERAL_REGISTER_10 = std_EPHEMERAL_REGISTER_0 + 0xa,
std_EPHEMERAL_REGISTER_11 = std_EPHEMERAL_REGISTER_0 + 0xb,
std_EPHEMERAL_REGISTER_12 = std_EPHEMERAL_REGISTER_0 + 0xc,
std_EPHEMERAL_REGISTER_13 = std_EPHEMERAL_REGISTER_0 + 0xd,
std_EPHEMERAL_REGISTER_14 = std_EPHEMERAL_REGISTER_0 + 0xe,
std_EPHEMERAL_REGISTER_15 = std_EPHEMERAL_REGISTER_0 + 0xf,
};

View file

@ -47,6 +47,7 @@
#include "virtual/Stack.h"
#include "virtual/Call.h"
#include "virtual/FastCall.h"
#include "virtual/Container.h"
#include "../Declaration.h"
@ -89,15 +90,54 @@ namespace Instruction {
addOperator("LOAD", 2, Load::fromTokens);
addOperator("LOAD_DIRECT", 2, Load::fromDirectTokens);
//Using NOT x = 255 - x. Cannot accept offsets
// NOT dest, source
//Using NOT x = 255 - x.
addOperator("NOT", 2, [](const parseOperatorResult &op, const std::vector<Token> &tokens) -> std::unique_ptr<Instruction> {
if(op.offset1 != 0){
throw std::runtime_error("NOT cannot use addressing offsets");
auto c = std::make_unique<Container>("NOT op with offset");
c->addInstruction(std::make_unique<Copy>(AddressWithOffset{(uint32_t) MgmtRegisters::std_SCRATCH_0, 0}, AddressWithOffset{tokens.at(1).getNumericValue(), op.offset1}, 1));
c->addInstruction(std::make_unique<Calc>(Calc::Operation::SUB, 0,
(uint32_t) MgmtRegisters::std_SCRATCH_0,
(uint32_t)MgmtRegisters::INTERNAL_REGISTER_ALWAYS_FFFFFFFF,
(uint32_t) MgmtRegisters::std_SCRATCH_0));
c->addInstruction(std::make_unique<Copy>(AddressWithOffset{tokens.at(1).getNumericValue(), op.offset2}, AddressWithOffset{(uint32_t) MgmtRegisters::std_SCRATCH_0, 0}, 1));
return std::move(c);
}
return std::make_unique<Calc>(Calc::Operation::SUB, 0,
auto i = std::make_unique<Calc>(Calc::Operation::SUB, 0,
tokens.at(0).getNumericValue(),
(uint32_t)MgmtRegisters::INTERNAL_REGISTER_ALWAYS_FFFFFFFF,
tokens.at(1).getNumericValue());
i->comment = "NOT op";
return std::move(i);
});
//XOR P1, P2 = A, P3 = B
addOperator("XOR", 3, [](const parseOperatorResult &op, const std::vector<Token> &tokens) -> std::unique_ptr<Instruction> {
if(op.offset1 != 0){
throw std::runtime_error("XOR cannot use addressing offsets");
}
auto c = std::make_unique<Container>("XOR op = a + b - (a & b) - (a & b)");
/*
* Non-offset version
* AND S1, A, B
* ADD S0, A, B
* SUB S0, S0, S1
* SUB P1, S0, S1
*/
if(tokens.at(2).getType() == Token::Type::Immediate){
c->addInstruction(std::make_unique<CalcImm>(Calc::Operation::AND, 0, (uint32_t) MgmtRegisters::std_SCRATCH_1, tokens.at(1).getNumericValue(), tokens.at(2).getNumericValue()), "XOR, s1 = a & b");
c->addInstruction(std::make_unique<CalcImm>(Calc::Operation::ADD, 0, (uint32_t) MgmtRegisters::std_SCRATCH_0, tokens.at(1).getNumericValue(), tokens.at(2).getNumericValue()), "XOR, s0 = a + b");
}else{
c->addInstruction(std::make_unique<Calc>(Calc::Operation::AND, 0, (uint32_t) MgmtRegisters::std_SCRATCH_1, tokens.at(1).getNumericValue(), tokens.at(2).getNumericValue()), "XOR, s1 = a & b");
c->addInstruction(std::make_unique<Calc>(Calc::Operation::ADD, 0, (uint32_t) MgmtRegisters::std_SCRATCH_0, tokens.at(1).getNumericValue(), tokens.at(2).getNumericValue()), "XOR, s0 = a + b");
}
c->addInstruction(std::make_unique<Calc>(Calc::Operation::SUB, 0, (uint32_t) MgmtRegisters::std_SCRATCH_0, (uint32_t) MgmtRegisters::std_SCRATCH_0, (uint32_t) MgmtRegisters::std_SCRATCH_1), "XOR, s0 = s0 - s1");
c->addInstruction(std::make_unique<Calc>(Calc::Operation::SUB, 0, tokens.at(0).getNumericValue(), (uint32_t) MgmtRegisters::std_SCRATCH_0, (uint32_t) MgmtRegisters::std_SCRATCH_1), "XOR, result = s0 - s1");
return std::move(c);
});
addOperator("AND", 3, CalcImm::fromAndTokens);

View file

@ -47,6 +47,7 @@ namespace Instruction {
uint32_t _address{};
uint32_t _endAddress{};
public:
std::string comment;
virtual ~Instruction()= default;
@ -83,8 +84,8 @@ namespace Instruction {
virtual CommandOp getCommand() const = 0;
virtual std::string getComment() const {
return "";
virtual const std::string& getComment() const {
return comment;
};
void setAddress(uint32_t address){

View file

@ -92,13 +92,13 @@ namespace Instruction {
}
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<Copy>(AddressWithOffset{(uint32_t)MgmtRegisters::std_RETURN_VALUE, 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<Write>(AddressWithOffset{(uint32_t)MgmtRegisters::std_RETURN_VALUE, 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}));
}

View file

@ -0,0 +1,74 @@
/*****************************************************************************
* 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 <utility>
#include "../Instruction.h"
#include "../../BaseRegisters.h"
namespace Instruction {
class Container : public Instruction {
private:
std::vector<std::unique_ptr<Instruction>> instructions;
public:
explicit Container(const std::string& c = ""){
comment = c;
}
void addInstruction(std::unique_ptr<Instruction> instruction, const std::string& c = ""){
instructions.emplace_back(std::move(instruction));
instructions.back()->comment = c;
}
CommandOp getCommand() const override {
return CommandOp::END;
};
std::vector<uint8_t> toBytes() const override{
std::vector<uint8_t> v;
for (auto &i : instructions) {
auto b = i->toBytes();
v.insert(v.end(), b.begin(), b.end());
}
return v;
}
size_t getByteSize() const override{
size_t s = 0;
for(auto& i : instructions){
s += i->getByteSize();
}
return s;
}
};
}

View file

@ -75,9 +75,9 @@ namespace Instruction{
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
instructions.push_back(std::make_unique<Copy>(AddressWithOffset{(uint32_t)MgmtRegisters::std_PARAMETER_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()}));
instructions.push_back(std::make_unique<Write>(AddressWithOffset{(uint32_t)MgmtRegisters::std_PARAMETER_1 + offset, 0}, std::vector<uint32_t>{t.getNumericValue()}));
}
}
++offset;

View file

@ -33,7 +33,6 @@ namespace Instruction {
//Akin to __fastcall, but the caller cleans up the stack
class FastCall : public Instruction {
private:
std::string comment;
std::vector<std::unique_ptr<Instruction>> instructions;
void initData(const std::vector<Token>& data);
void takedownData(const std::vector<Token>& data);
@ -48,10 +47,6 @@ namespace Instruction {
std::vector<uint8_t> toBytes() const override;
std::string getComment() const override {
return comment;
};
size_t getByteSize() const override{
size_t s = 0;
for(auto& i : instructions){

View file

@ -234,11 +234,6 @@ namespace Instruction {
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) {

View file

@ -196,9 +196,6 @@ namespace Instruction {
}
return s;
}
static std::unique_ptr<Instruction>
fromTokens(const Instruction::parseOperatorResult &op, const std::vector<Token> &tokens);
};
class PopPeek : public Instruction {