rrcc/src/instructions/Instruction.cpp

351 lines
20 KiB
C++

/*****************************************************************************
* 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 "Instruction.h"
#include "Write.h"
#include "Copy.h"
#include "Load.h"
#include "Init.h"
#include "Calc.h"
#include "CalcImm.h"
#include "Branch.h"
#include "Poll.h"
#include "Loop.h"
#include "Jump.h"
#include "Return.h"
#include "Set.h"
#include "Wait.h"
#include "End.h"
#include "../Declaration.h"
namespace Instruction {
std::unique_ptr<Instruction> Instruction::getCommandForDeclaration(const Declaration &declaration) {
size_t offset = 0;
for (auto &t : declaration.tokens) {
if (t.getType() == Token::Type::Operator) {
break;
}
++offset;
}
if (offset == declaration.tokens.size()) {
return nullptr;
}
offset++;
uint32_t paramCount = declaration.tokens.size() - offset;
std::string operatorValue = declaration.tokens.at(offset - 1).getTextValue();
uint8_t addressOffset = 0;
uint8_t addressOffset2 = 0;
if (
((operatorValue == "WRITE") || (operatorValue == "WRITE~1" && (addressOffset = 1)) ||
(operatorValue == "WRITE~2" && (addressOffset = 2)) ||
(operatorValue == "WRITE~3" && (addressOffset = 3)))
&& paramCount >= 2
) {
std::vector<uint32_t> data;
for (auto it = declaration.tokens.begin() + offset + 1; it != declaration.tokens.end(); ++it) {
data.emplace_back(it->getNumericValue());
}
return std::make_unique<Write>(
AddressWithOffset{declaration.tokens.at(offset).getNumericValue(), addressOffset}, data);
} else if (
((operatorValue == "COPY") ||
(operatorValue == "COPY~01" && (addressOffset2 = 1)) ||
(operatorValue == "COPY~02" && (addressOffset2 = 2)) ||
(operatorValue == "COPY~03" && (addressOffset2 = 3)) ||
(operatorValue == "COPY~10" && (addressOffset = 1)) ||
(operatorValue == "COPY~11" && (addressOffset = 1) && (addressOffset2 = 1)) ||
(operatorValue == "COPY~12" && (addressOffset = 1) && (addressOffset2 = 2)) ||
(operatorValue == "COPY~13" && (addressOffset = 1) && (addressOffset2 = 3)) ||
(operatorValue == "COPY~20" && (addressOffset = 2)) ||
(operatorValue == "COPY~21" && (addressOffset = 2) && (addressOffset2 = 1)) ||
(operatorValue == "COPY~22" && (addressOffset = 2) && (addressOffset2 = 2)) ||
(operatorValue == "COPY~23" && (addressOffset = 2) && (addressOffset2 = 3)) ||
(operatorValue == "COPY~30" && (addressOffset = 3)) ||
(operatorValue == "COPY~31" && (addressOffset = 3) && (addressOffset2 = 1)) ||
(operatorValue == "COPY~32" && (addressOffset = 3) && (addressOffset2 = 2)) ||
(operatorValue == "COPY~33" && (addressOffset = 3) && (addressOffset2 = 3))
)
&& paramCount >= 2
) {
return std::make_unique<Copy>(
AddressWithOffset{declaration.tokens.at(offset).getNumericValue(), addressOffset},
AddressWithOffset{declaration.tokens.at(offset + 1).getNumericValue(), addressOffset2},
declaration.tokens.at(offset + 3).getNumericValue());
} else if (
((operatorValue == "LOAD") || (operatorValue == "LOAD~1" && (addressOffset = 1)) ||
(operatorValue == "LOAD~2" && (addressOffset = 2)) ||
(operatorValue == "LOAD~3" && (addressOffset = 3)))
&& paramCount >= 2
) {
std::vector<uint32_t> data;
for (auto it = declaration.tokens.begin() + offset + 1; it != declaration.tokens.end(); ++it) {
data.emplace_back(it->getNumericValue());
}
return std::make_unique<Load>(
AddressWithOffset{declaration.tokens.at(offset).getNumericValue(), addressOffset}, 1, data);
} else if (
((operatorValue == "LOAD_DIRECT") || (operatorValue == "LOAD_DIRECT~1" && (addressOffset = 1)) ||
(operatorValue == "LOAD_DIRECT~2" && (addressOffset = 2)) ||
(operatorValue == "LOAD_DIRECT~3" && (addressOffset = 3)))
&& paramCount >= 2
) {
std::vector<uint32_t> data;
for (auto it = declaration.tokens.begin() + offset + 1; it != declaration.tokens.end(); ++it) {
data.emplace_back(it->getNumericValue());
}
return std::make_unique<Load>(
AddressWithOffset{declaration.tokens.at(offset).getNumericValue(), addressOffset}, 0, data);
}
//TODO INIT
else if (
((operatorValue == "AND") || (operatorValue == "AND~1" && (addressOffset = 1)) ||
(operatorValue == "AND~2" && (addressOffset = 2)) || (operatorValue == "AND~3" && (addressOffset = 3)))
&& paramCount >= 3
) {
if (declaration.tokens.at(offset + 2).getType() == Token::Type::Immediate) {
return std::make_unique<CalcImm>(Calc::Operation::AND, addressOffset,
declaration.tokens.at(offset).getNumericValue(),
declaration.tokens.at(offset + 1).getNumericValue(),
declaration.tokens.at(offset + 2).getNumericValue());
} else {
return std::make_unique<Calc>(Calc::Operation::AND, addressOffset,
declaration.tokens.at(offset).getNumericValue(),
declaration.tokens.at(offset + 1).getNumericValue(),
declaration.tokens.at(offset + 2).getNumericValue());
}
} else if (
((operatorValue == "OR") || (operatorValue == "OR~1" && (addressOffset = 1)) ||
(operatorValue == "OR~2" && (addressOffset = 2)) || (operatorValue == "OR~3" && (addressOffset = 3)))
&& paramCount >= 3
) {
if (declaration.tokens.at(offset + 2).getType() == Token::Type::Immediate) {
return std::make_unique<CalcImm>(Calc::Operation::OR, addressOffset,
declaration.tokens.at(offset).getNumericValue(),
declaration.tokens.at(offset + 1).getNumericValue(),
declaration.tokens.at(offset + 2).getNumericValue());
} else {
return std::make_unique<Calc>(Calc::Operation::OR, addressOffset,
declaration.tokens.at(offset).getNumericValue(),
declaration.tokens.at(offset + 1).getNumericValue(),
declaration.tokens.at(offset + 2).getNumericValue());
}
} else if (
((operatorValue == "ADD") || (operatorValue == "ADD~1" && (addressOffset = 1)) ||
(operatorValue == "ADD~2" && (addressOffset = 2)) || (operatorValue == "ADD~3" && (addressOffset = 3)))
&& paramCount >= 3
) {
if (declaration.tokens.at(offset + 2).getType() == Token::Type::Immediate) {
return std::make_unique<CalcImm>(Calc::Operation::ADD, addressOffset,
declaration.tokens.at(offset).getNumericValue(),
declaration.tokens.at(offset + 1).getNumericValue(),
declaration.tokens.at(offset + 2).getNumericValue());
} else {
return std::make_unique<Calc>(Calc::Operation::ADD, addressOffset,
declaration.tokens.at(offset).getNumericValue(),
declaration.tokens.at(offset + 1).getNumericValue(),
declaration.tokens.at(offset + 2).getNumericValue());
}
} else if (
((operatorValue == "SUB") || (operatorValue == "SUB~1" && (addressOffset = 1)) ||
(operatorValue == "SUB~2" && (addressOffset = 2)) || (operatorValue == "SUB~3" && (addressOffset = 3)))
&& paramCount >= 3
) {
if (declaration.tokens.at(offset + 2).getType() == Token::Type::Immediate) {
return std::make_unique<CalcImm>(Calc::Operation::SUB, addressOffset,
declaration.tokens.at(offset).getNumericValue(),
declaration.tokens.at(offset + 1).getNumericValue(),
declaration.tokens.at(offset + 2).getNumericValue());
} else {
return std::make_unique<Calc>(Calc::Operation::SUB, addressOffset,
declaration.tokens.at(offset).getNumericValue(),
declaration.tokens.at(offset + 1).getNumericValue(),
declaration.tokens.at(offset + 2).getNumericValue());
}
} else if (
((operatorValue == "LSHIFT") || (operatorValue == "LSHIFT~1" && (addressOffset = 1)) ||
(operatorValue == "LSHIFT~2" && (addressOffset = 2)) ||
(operatorValue == "LSHIFT~3" && (addressOffset = 3)))
&& paramCount >= 3
) {
if (declaration.tokens.at(offset + 2).getType() == Token::Type::Immediate) {
return std::make_unique<CalcImm>(Calc::Operation::LSHIFT, addressOffset,
declaration.tokens.at(offset).getNumericValue(),
declaration.tokens.at(offset + 1).getNumericValue(),
declaration.tokens.at(offset + 2).getNumericValue());
} else {
return std::make_unique<Calc>(Calc::Operation::LSHIFT, addressOffset,
declaration.tokens.at(offset).getNumericValue(),
declaration.tokens.at(offset + 1).getNumericValue(),
declaration.tokens.at(offset + 2).getNumericValue());
}
} else if (
((operatorValue == "RSHIFT") || (operatorValue == "RSHIFT~1" && (addressOffset = 1)) ||
(operatorValue == "RSHIFT~2" && (addressOffset = 2)) ||
(operatorValue == "RSHIFT~3" && (addressOffset = 3)))
&& paramCount >= 3
) {
if (declaration.tokens.at(offset + 2).getType() == Token::Type::Immediate) {
return std::make_unique<CalcImm>(Calc::Operation::RSHIFT, addressOffset,
declaration.tokens.at(offset).getNumericValue(),
declaration.tokens.at(offset + 1).getNumericValue(),
declaration.tokens.at(offset + 2).getNumericValue());
} else {
return std::make_unique<Calc>(Calc::Operation::RSHIFT, addressOffset,
declaration.tokens.at(offset).getNumericValue(),
declaration.tokens.at(offset + 1).getNumericValue(),
declaration.tokens.at(offset + 2).getNumericValue());
}
} else if (
((operatorValue == "ARSHIFT") || (operatorValue == "ARSHIFT~1" && (addressOffset = 1)) ||
(operatorValue == "ARSHIFT~2" && (addressOffset = 2)) ||
(operatorValue == "ARSHIFT~3" && (addressOffset = 3)))
&& paramCount >= 3
) {
if (declaration.tokens.at(offset + 2).getType() == Token::Type::Immediate) {
return std::make_unique<CalcImm>(Calc::Operation::ARSHIFT, addressOffset,
declaration.tokens.at(offset).getNumericValue(),
declaration.tokens.at(offset + 1).getNumericValue(),
declaration.tokens.at(offset + 2).getNumericValue());
} else {
return std::make_unique<Calc>(Calc::Operation::ARSHIFT, addressOffset,
declaration.tokens.at(offset).getNumericValue(),
declaration.tokens.at(offset + 1).getNumericValue(),
declaration.tokens.at(offset + 2).getNumericValue());
}
} else if (
((operatorValue == "BEQ") || (operatorValue == "BEQ~1" && (addressOffset = 1)) ||
(operatorValue == "BEQ~2" && (addressOffset = 2)) || (operatorValue == "BEQ~3" && (addressOffset = 3)))
&& paramCount >= 4
) {
return std::make_unique<Branch>(
AddressWithOffset{declaration.tokens.at(offset).getNumericValue(), addressOffset}, 1,
declaration.tokens.at(offset + 1).getNumericValue(),
declaration.tokens.at(offset + 2).getNumericValue(),
declaration.tokens.at(offset + 3).getNumericValue());
} else if (
((operatorValue == "BNE") || (operatorValue == "BNE~1" && (addressOffset = 1)) ||
(operatorValue == "BNE~2" && (addressOffset = 2)) || (operatorValue == "BNE~3" && (addressOffset = 3)))
&& paramCount >= 4
) {
return std::make_unique<Branch>(
AddressWithOffset{declaration.tokens.at(offset).getNumericValue(), addressOffset}, 0,
declaration.tokens.at(offset + 1).getNumericValue(),
declaration.tokens.at(offset + 2).getNumericValue(),
declaration.tokens.at(offset + 3).getNumericValue());
} else if (
((operatorValue == "PEQ") || (operatorValue == "PEQ~1" && (addressOffset = 1)) ||
(operatorValue == "PEQ~2" && (addressOffset = 2)) || (operatorValue == "PEQ~3" && (addressOffset = 3)))
&& paramCount >= 6
) {
return std::make_unique<Poll>(
AddressWithOffset{declaration.tokens.at(offset).getNumericValue(), addressOffset}, 1,
declaration.tokens.at(offset + 1).getNumericValue(),
declaration.tokens.at(offset + 2).getNumericValue(),
declaration.tokens.at(offset + 3).getNumericValue(),
declaration.tokens.at(offset + 4).getNumericValue(),
declaration.tokens.at(offset + 5).getNumericValue());
} else if (
((operatorValue == "PNE") || (operatorValue == "PNE~1" && (addressOffset = 1)) ||
(operatorValue == "PNE~2" && (addressOffset = 2)) || (operatorValue == "PNE~3" && (addressOffset = 3)))
&& paramCount >= 6
) {
return std::make_unique<Poll>(
AddressWithOffset{declaration.tokens.at(offset).getNumericValue(), addressOffset}, 1,
declaration.tokens.at(offset + 1).getNumericValue(),
declaration.tokens.at(offset + 2).getNumericValue(),
declaration.tokens.at(offset + 3).getNumericValue(),
declaration.tokens.at(offset + 4).getNumericValue(),
declaration.tokens.at(offset + 5).getNumericValue());
} else if (
((operatorValue == "LOOP") || (operatorValue == "LOOP~1" && (addressOffset = 1)) ||
(operatorValue == "LOOP~2" && (addressOffset = 2)) ||
(operatorValue == "LOOP~3" && (addressOffset = 3)))
&& paramCount >= 1
) {
return std::make_unique<Loop>(
0,
declaration.tokens.at(offset).getNumericValue());
} else if (
((operatorValue == "LOOPB") || (operatorValue == "LOOPB~1" && (addressOffset = 1)) ||
(operatorValue == "LOOPB~2" && (addressOffset = 2)) ||
(operatorValue == "LOOPB~3" && (addressOffset = 3)))
&& paramCount >= 1
) {
return std::make_unique<Loop>(
1,
declaration.tokens.at(offset).getNumericValue());
} else if (
((operatorValue == "CALL") || (operatorValue == "CALL~1" && (addressOffset = 1)) ||
(operatorValue == "CALL~2" && (addressOffset = 2)) ||
(operatorValue == "CALL~3" && (addressOffset = 3)))
&& paramCount >= 1
) {
if (declaration.tokens.at(offset).getType() == Token::Type::CodeLocation ||
declaration.tokens.at(offset).getType() == Token::Type::CodeLabel) {
return std::make_unique<Jump>(
declaration.tokens.at(offset).getNumericValue());
} else {
return std::make_unique<Return>(
AddressWithOffset{declaration.tokens.at(offset).getNumericValue(), addressOffset});
}
} else if (
((operatorValue == "SET") || (operatorValue == "SET~1" && (addressOffset = 1)) ||
(operatorValue == "SET~2" && (addressOffset = 2)) || (operatorValue == "SET~3" && (addressOffset = 3)))
&& paramCount >= 3
) {
return std::make_unique<Set>(
AddressWithOffset{declaration.tokens.at(offset).getNumericValue(), addressOffset},
declaration.tokens.at(offset + 1).getNumericValue(),
declaration.tokens.at(offset + 2).getNumericValue());
} else if (operatorValue == "WAIT" && paramCount >= 1) {
return std::make_unique<Wait>(declaration.tokens.at(offset).getNumericValue());
} else if (operatorValue == "END") {
return std::make_unique<End>();
}
return nullptr;
}
}