351 lines
20 KiB
C++
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;
|
|
}
|
|
}
|
|
|