Compare commits
7 commits
6f8d12ee32
...
c4a98361b1
Author | SHA1 | Date | |
---|---|---|---|
DataHoarder | c4a98361b1 | ||
DataHoarder | 6d8b3f0e09 | ||
DataHoarder | 98e3e77686 | ||
DataHoarder | 1cce604661 | ||
DataHoarder | ee8c4ed7de | ||
DataHoarder | 7ffaa962a3 | ||
DataHoarder | f7b4fa92db |
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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,
|
||||
};
|
|
@ -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);
|
||||
|
|
|
@ -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){
|
||||
|
|
|
@ -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}));
|
||||
}
|
||||
|
|
74
src/instructions/virtual/Container.h
Normal file
74
src/instructions/virtual/Container.h
Normal 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;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
|
||||
}
|
|
@ -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;
|
||||
|
|
|
@ -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){
|
||||
|
|
|
@ -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) {
|
||||
|
|
|
@ -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 {
|
||||
|
|
Loading…
Reference in a new issue