Create tagged assembly, context, and known jump table. Split "decode" output into functions

This commit is contained in:
DataHoarder 2020-12-28 20:52:04 +01:00
parent 58b55c20ce
commit 88e7f0d8b8
40 changed files with 673 additions and 113 deletions

View file

@ -7,6 +7,7 @@ set(SOURCE_FILES
src/ImageFormat.cpp src/ImageFormat.h
src/SmallFirmwareFormat.cpp src/SmallFirmwareFormat.h
src/instructions/AddressOffset.h
src/instructions/Instruction.cpp src/instructions/Instruction.h
src/instructions/Write.cpp src/instructions/Write.h
src/instructions/Copy.cpp src/instructions/Copy.h
@ -26,7 +27,8 @@ set(SOURCE_FILES
src/Registers.cpp src/Registers.h
src/AnalysisState.cpp src/AnalysisState.h
src/Configuration.cpp src/Configuration.h
)
src/OutputContext.cpp src/OutputContext.h
)
add_library(rrcimage STATIC ${SOURCE_FILES})

View file

@ -34,4 +34,16 @@ uint32_t AnalysisState::getAddressOffset(uint8_t offsetEntry) const {
return 0;
}
return getRegister((uint32_t) KnownRegisters::BSM_ADDR_OFFSET_0 + offsetEntry);
}
}
uint32_t AnalysisState::getRegister(const Instruction::AddressWithOffset &address) const {
return getRegister(getAddressWithOffset(address));
}
void AnalysisState::setRegister(const Instruction::AddressWithOffset &address, uint32_t value) {
setRegister(getAddressWithOffset(address), value);
}
uint32_t AnalysisState::getAddressWithOffset(const Instruction::AddressWithOffset &address) const {
return address.address + getAddressOffset(address.offset);
}

View file

@ -30,10 +30,23 @@
#include <cstdint>
#include <unordered_map>
#include <algorithm>
#include "SmallFirmwareFormat.h"
#include "instructions/AddressOffset.h"
enum class JumpKind{
Continue,
Absolute,
Branch,
Loop,
Return
};
typedef std::unordered_map<uint32_t, std::vector<std::pair<uint32_t, JumpKind>>> AnalysisJumpTable;
class AnalysisState {
public:
std::unordered_map<uint32_t, uint32_t> memory;
uint32_t previous;
uint32_t current;
@ -41,13 +54,24 @@ public:
SmallFirmwareFormat pciSPICOFirmware;
SmallFirmwareFormat pciSerDesFirmware;
AnalysisState(uint32_t initial) : current(initial), previous(0) {
AnalysisJumpTable& jumpTable;
void addKnownJump(uint32_t to, uint32_t from, JumpKind kind){
if(jumpTable.find(to) == jumpTable.end()){
jumpTable[to] = std::vector<std::pair<uint32_t, JumpKind>>{{from, kind}};
}else if(std::find(jumpTable[to].begin(), jumpTable[to].end(), std::pair<uint32_t, JumpKind>(from, kind)) == jumpTable[to].end()){
jumpTable[to].emplace_back(from, kind);
}
}
AnalysisState(uint32_t initial, AnalysisJumpTable& table) : current(initial), previous(0), jumpTable(table) {
}
AnalysisState(const AnalysisState &oldState) : current(oldState.current), previous(oldState.previous),
memory(oldState.memory), pciSPICOFirmware(oldState.pciSPICOFirmware),
pciSerDesFirmware(oldState.pciSerDesFirmware) {
pciSerDesFirmware(oldState.pciSerDesFirmware), jumpTable(oldState.jumpTable) {
}
@ -55,13 +79,19 @@ public:
return current == other.current && memory == other.memory;
}
void setRegister(const Instruction::AddressWithOffset& address, uint32_t value);
void setRegister(uint32_t addr, uint32_t value) {
memory[addr] = value;
}
uint32_t getRegister(const Instruction::AddressWithOffset& address) const;
uint32_t getRegister(uint32_t addr) const {
return memory.find(addr) == memory.end() ? 0 : memory.at(addr);
}
uint32_t getAddressWithOffset(const Instruction::AddressWithOffset& address) const;
uint32_t getAddressOffset(uint8_t offsetEntry) const;
};

View file

@ -112,7 +112,7 @@ ImageFormat ImageFormat::fromBytes(const std::vector<uint8_t> &imageBytes) {
std::vector<uint8_t> ImageFormat::toBytes() const {
std::vector<uint8_t> bytes;
bytes.resize(baseImage.size() - 1, 0xFF);
bytes.resize(getBaseImage().size() - 1, 0xFF);
uint32_t offset = 0;
@ -123,7 +123,7 @@ std::vector<uint8_t> ImageFormat::toBytes() const {
bytes[offset++] = header.baseAddress & 0xFF;
for (; offset < CFG_HEADER; ++offset) {
bytes[offset] = baseImage[offset];
bytes[offset] = getBaseImage()[offset];
}
bytes[offset++] = cfgHeader.length;
@ -132,7 +132,7 @@ std::vector<uint8_t> ImageFormat::toBytes() const {
bytes[offset++] = cfgHeader.base & 0xFF;
for (; offset < CFG_SIGNATURE; ++offset) {
bytes[offset] = baseImage[offset];
bytes[offset] = getBaseImage()[offset];
}
std::copy(imageSignature.begin(), imageSignature.end(), bytes.begin() + offset);
@ -140,7 +140,7 @@ std::vector<uint8_t> ImageFormat::toBytes() const {
offset += imageSignature.length();
for (; offset < cfgHeader.base; ++offset) {
bytes[offset] = baseImage[offset];
bytes[offset] = getBaseImage()[offset];
}
bytes[offset++] = cfg.fileFormat;
@ -150,7 +150,7 @@ std::vector<uint8_t> ImageFormat::toBytes() const {
bytes[offset++] = (cfg.length >> 4) & 0xFF;
for (; offset < cfgHeader.base + CFG_LENGTH; ++offset) {
bytes[offset] = baseImage[offset];
bytes[offset] = getBaseImage()[offset];
}
if (cfg.version == 0) {
@ -168,7 +168,7 @@ std::vector<uint8_t> ImageFormat::toBytes() const {
bytes[offset] = 0xFF;
}
std::copy(baseImage.begin() + offset, baseImage.end(), bytes.begin() + offset);
std::copy(getBaseImage().begin() + offset, getBaseImage().end(), bytes.begin() + offset);
for (const auto &entry : instructions) {
auto data = entry.second->toBytes();
@ -180,12 +180,14 @@ std::vector<uint8_t> ImageFormat::toBytes() const {
void ImageFormat::decodeAnalyzeInstructionsAt(uint32_t offset) {
jumpTable.clear();
std::queue<AnalysisState> savedStates;
std::vector<AnalysisState> branchingStates;
std::unordered_map<uint32_t, bool> jumpsUsed;
AnalysisState baseState(offset);
AnalysisState baseState(offset, jumpTable);
savedStates.push(baseState);
@ -209,7 +211,7 @@ void ImageFormat::decodeAnalyzeInstructionsAt(uint32_t offset) {
break;
} else if (findInstructionByAddress(state.current) == nullptr) {
auto decodedInstruction = Instruction::Instruction::decodeInstructionFromBytes(state.current,
baseImage);
getBaseImage());
instructions[decodedInstruction->getAddress()] = std::move(decodedInstruction);
}

View file

@ -63,6 +63,29 @@ public:
void decodeAnalyzeInstructionsAt(uint32_t offset);
const std::unique_ptr<Instruction::Instruction> &findConstInstructionByAddress(uint32_t addr, bool indirect = false) const {
if (instructions.find(addr) != instructions.end()) {
return instructions.find(addr)->second;
}
if (indirect) {
for (auto &instruction : instructions) {
if (
(instruction.second->getEndAddress() == 0 && addr == instruction.second->getAddress())
|| (
instruction.second->getEndAddress() != 0
&& addr >= instruction.second->getAddress()
&& addr < instruction.second->getEndAddress()
)
) {
return instruction.second;
}
}
}
return NULL_INSTRUCTION;
}
std::unique_ptr<Instruction::Instruction> &findInstructionByAddress(uint32_t addr, bool indirect = false) {
if (instructions.find(addr) != instructions.end()) {
return instructions.find(addr)->second;
@ -98,6 +121,10 @@ public:
return instructions;
}
const auto& getJumpTable() const{
return jumpTable;
}
const auto &getBaseImage() const {
return baseImage;
}
@ -145,4 +172,6 @@ private:
std::map<uint32_t, std::unique_ptr<Instruction::Instruction>> instructions;
std::vector<uint8_t> baseImage;
AnalysisJumpTable jumpTable;
};

124
src/OutputContext.cpp Normal file
View file

@ -0,0 +1,124 @@
/*****************************************************************************
* Copyright (c) 2020, rrcSmall 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 <sstream>
#include <iomanip>
#include "OutputContext.h"
std::string OutputContext::getLabel(uint32_t location, bool force) const{
if(mappings.find(location) != mappings.end()){
return mappings.at(location);
}
if(force){
std::stringstream s;
s << "func_" << std::hex << std::setw(6) << std::setfill('0') << location;
return s.str();
}
return "";
}
std::string OutputContext::getComment(uint32_t location) const{
if(comments.find(location) != comments.end()){
return " ; " + comments.at(location);
}
return "";
}
std::string OutputContext::getDataHeader(uint32_t location) const {
std::stringstream s;
s << std::hex << std::setw(6) << std::setfill('0') << location << " ";
for(uint32_t i = location; i < location + 4; ++i){
s << std::hex << std::setw(2) << std::setfill('0') << (uint32_t)image.getBaseImage().at(i) << " ";
}
s << " ";
return s.str();
}
std::string OutputContext::getDataEntry(uint32_t location, const std::string &representation) const {
return getDataHeader(location) + representation + getComment(location);
}
std::string OutputContext::getInstructionString(const Instruction::Instruction& instruction) const {
std::string output;
for(auto& l : instruction.toOutputFormat(*this)){
output += getDataEntry(l.location, l.format) + "\n";
}
return output;
}
void OutputContext::analyze() {
const auto& table = image.getJumpTable();
for (auto& e : table){
std::stringstream from;
from << "XREF.CallFrom: ";
bool hasContinue = false;
bool justReturn = true;
for(auto& j : e.second){
if(j.second != JumpKind::Return){
justReturn = false;
}
if(j.second != JumpKind::Continue){
from << std::hex << std::setw(6) << std::setfill('0') << j.first << "(";
switch (j.second) {
case JumpKind::Absolute:
from << "Absolute";
break;
case JumpKind::Branch:
from << "Branch";
break;
case JumpKind::Loop:
from << "Loop";
break;
case JumpKind::Return:
from << "Return";
break;
}
from << "), ";
} else {
hasContinue = true;
}
}
if(!hasContinue){
if(!e.second.empty() && justReturn){
auto& instruction = image.findConstInstructionByAddress(e.first - 1, true);
if(instruction != nullptr && instruction->getCommand() == Instruction::Instruction::CommandOp::JUMP){
//TODO, mark join?
}else{
addMapping(e.first, getLabel(e.first, true));
}
}else{
addMapping(e.first, getLabel(e.first, true));
}
}
if(e.second.size() > 1 || (!hasContinue && !e.second.empty())){
addComment(e.first, from.str());
}
}
}

77
src/OutputContext.h Normal file
View file

@ -0,0 +1,77 @@
/*****************************************************************************
* Copyright (c) 2020, rrcSmall 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 <cstdint>
#include <unordered_map>
#include <vector>
#include <algorithm>
#include "ImageFormat.h"
class OutputContext {
public:
private:
const ImageFormat& image;
std::unordered_map<uint32_t, std::string> mappings;
std::unordered_map<uint32_t, std::string> comments;
public:
OutputContext(const ImageFormat& image) : image(image){
}
void addMapping(uint32_t location, const std::string& name){
if(comments.find(location) == comments.end()) {
mappings[location] = name;
}
}
void addComment(uint32_t location, const std::string& comment){
if(comments.find(location) != comments.end()){
comments[location] = comment + " --- " + comments[location];
}else{
comments[location] = comment;
}
}
std::string getLabel(uint32_t location, bool force = true) const;
std::string getComment(uint32_t location) const;
std::string getDataHeader(uint32_t location) const;
std::string getDataEntry(uint32_t location, const std::string& representation = "") const;
std::string getInstructionString(const Instruction::Instruction& instruction) const;
void analyze();
};

View file

@ -180,6 +180,10 @@ std::string getAddressRegisterName(uint32_t addr, uint8_t offset) {
return s.str();
}
std::string getAddressRegisterName(const Instruction::AddressWithOffset& address) {
return getAddressRegisterName(address.address, address.offset);
}
KnownRegisters getScratchRegister(uint32_t offset) {
return static_cast<KnownRegisters>((uint32_t) KnownRegisters::BSM_SCRATCH_START + offset);
}

View file

@ -30,6 +30,7 @@
#include <cstdint>
#include <string>
#include "instructions/AddressOffset.h"
enum class KnownRegisters : uint32_t {
PCIE_MASTER_SPICO_FIRMWARE_SPECIAL_REGISTER = 0x0,
@ -124,4 +125,5 @@ KnownRegisters getScratchRegister(uint32_t offset);
std::string getRegisterName(KnownRegisters addr);
std::string getAddressRegisterName(uint32_t addr, uint8_t offset = 0);
std::string getAddressRegisterName(uint32_t addr, uint8_t offset = 0);
std::string getAddressRegisterName(const Instruction::AddressWithOffset& address);

View file

@ -0,0 +1,35 @@
/*****************************************************************************
* Copyright (c) 2020, rrcSmall 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
namespace Instruction {
typedef struct {
uint32_t address: 24;
uint8_t offset: 2;
} AddressWithOffset;
}

View file

@ -29,6 +29,7 @@
#include "../Registers.h"
#include <iostream>
#include <iomanip>
#include "../OutputContext.h"
void Instruction::Branch::fromBytes(uint32_t offset, const std::vector<uint8_t> &bytes) {
_address = offset;
@ -36,11 +37,11 @@ void Instruction::Branch::fromBytes(uint32_t offset, const std::vector<uint8_t>
uint32_t command = bytes[offset++];
equality = (command >> 2) & 0b1;
addressOffset = command & 0b11;
address.offset = command & 0b11;
address = bytes[offset++] << 16;
address |= bytes[offset++] << 8;
address |= bytes[offset++];
address.address = bytes[offset++] << 16;
address.address |= bytes[offset++] << 8;
address.address |= bytes[offset++];
value = bytes[offset++] << 24;
value |= bytes[offset++] << 16;
@ -64,7 +65,7 @@ void Instruction::Branch::fromBytes(uint32_t offset, const std::vector<uint8_t>
std::string Instruction::Branch::toString() const {
std::stringstream op;
op << "BRANCH IF (" << getAddressRegisterName(address, addressOffset) << " & 0x" << std::hex << std::setw(8)
op << "BRANCH IF (" << getAddressRegisterName(address) << " & 0x" << std::hex << std::setw(8)
<< std::setfill('0') << mask << ")";
if (equality) {
op << " == ";
@ -77,6 +78,15 @@ std::string Instruction::Branch::toString() const {
return op.str();
}
std::vector<Instruction::OutputFormat> Instruction::Branch::toOutputFormat(const OutputContext &context) const {
return std::vector<OutputFormat>{
OutputFormat{getAddress(), dynamic_cast<std::stringstream&>(std::stringstream("") << "BRANCH" << " " << getAddressRegisterName(address) << (equality ? " == " : " != ")).str()},
OutputFormat{getAddress() + 4, dynamic_cast<std::stringstream&>(std::stringstream("") << " VALUE 0x" << std::hex << std::setw(8) << std::setfill('0') << value).str()},
OutputFormat{getAddress() + 8, dynamic_cast<std::stringstream&>(std::stringstream("") << " MASK 0x" << std::hex << std::setw(8) << std::setfill('0') << mask).str()},
OutputFormat{getAddress() + 12, dynamic_cast<std::stringstream&>(std::stringstream("") << " JUMP_ADDRESS " << context.getLabel(jumpAddress)).str()},
};
}
std::vector<uint32_t> Instruction::Branch::getPossibleBranches() const {
return std::vector<uint32_t>{_endAddress, jumpAddress};
}
@ -85,35 +95,37 @@ std::vector<std::pair<uint32_t, std::unordered_map<uint32_t, uint32_t>>>
Instruction::Branch::execute(AnalysisState &state) const {
std::vector<std::pair<uint32_t, std::unordered_map<uint32_t, uint32_t>>> branches;
uint32_t memoryOffset = state.getAddressOffset(addressOffset);
if ((state.getRegister(memoryOffset + address) & mask) == value) {
if ((state.getRegister(address) & mask) == value) {
state.current = equality ? jumpAddress : _endAddress;
std::unordered_map<uint32_t, uint32_t> branchedState;
branchedState[memoryOffset + address] =
state.getRegister(memoryOffset + address) | (equality ? ~value & mask : value);
branchedState[state.getAddressWithOffset(address)] =
state.getRegister(address) | (equality ? ~value & mask : value);
branches.emplace_back(equality ? _endAddress : jumpAddress, std::move(branchedState));
} else {
state.current = equality ? _endAddress : jumpAddress;
std::unordered_map<uint32_t, uint32_t> branchedState;
branchedState[memoryOffset + address] =
state.getRegister(memoryOffset + address) | (equality ? value : ~value & mask);
branchedState[state.getAddressWithOffset(address)] =
state.getRegister(address) | (equality ? value : ~value & mask);
branches.emplace_back(equality ? jumpAddress : _endAddress, std::move(branchedState));
}
state.addKnownJump(getEndAddress(), getAddress(), JumpKind::Continue);
state.addKnownJump(jumpAddress, getAddress(), JumpKind::Branch);
return branches;
}
std::vector<uint8_t> Instruction::Branch::toBytes() const {
std::vector<uint8_t> bytes;
bytes.emplace_back((uint8_t) getCommand() | (equality << 2) | addressOffset);
bytes.emplace_back((uint8_t) getCommand() | (equality << 2) | address.offset);
bytes.emplace_back((address >> 16) & 0xFF);
bytes.emplace_back((address >> 8) & 0xFF);
bytes.emplace_back(address & 0xFF);
bytes.emplace_back((address.address >> 16) & 0xFF);
bytes.emplace_back((address.address >> 8) & 0xFF);
bytes.emplace_back(address.address & 0xFF);
bytes.emplace_back((value >> 24) & 0xFF);
bytes.emplace_back((value >> 16) & 0xFF);

View file

@ -45,6 +45,7 @@ namespace Instruction {
std::vector<uint8_t> toBytes() const override;
std::string toString() const override;
std::vector<OutputFormat> toOutputFormat(const OutputContext& context) const override;
std::vector<uint32_t> getPossibleBranches() const override;
@ -52,9 +53,8 @@ namespace Instruction {
execute(AnalysisState &state) const override;
uint8_t addressOffset;
uint8_t equality;
uint32_t address;
AddressWithOffset address;
uint32_t value;
uint32_t mask;
uint32_t jumpAddress;

View file

@ -92,6 +92,42 @@ std::string Instruction::Calc::toString() const {
return op.str();
}
std::vector<Instruction::OutputFormat> Instruction::Calc::toOutputFormat(const OutputContext &context) const {
std::stringstream opname;
switch (operation) {
case Operation::AND:
opname << "AND";
break;
case Operation::OR:
opname << "OR";
break;
case Operation::ADD:
opname << "ADD";
break;
case Operation::SUB:
opname << "SUB";
break;
case Operation::LSHIFT:
opname << "LSHIFT";
break;
case Operation::RSHIFT:
opname << "RSHIFT";
break;
case Operation::ARSHIFT:
opname << "ARSHIFT";
break;
case Operation::UNDEFINED:
opname << "UNDEFINED";
break;
}
return std::vector<OutputFormat>{
OutputFormat{getAddress(), dynamic_cast<std::stringstream&>(opname << " " << getAddressRegisterName(addressDestination, addressOffset) << " = ").str()},
OutputFormat{getAddress() + 4, dynamic_cast<std::stringstream&>(std::stringstream("") << " SOURCE " << getAddressRegisterName(addressSource, addressOffset)).str()},
OutputFormat{getAddress() + 8, dynamic_cast<std::stringstream&>(std::stringstream("") << " TARGET " << getAddressRegisterName(addressTarget, addressOffset)).str()},
};
}
std::vector<uint32_t> Instruction::Calc::getPossibleBranches() const {
return std::vector<uint32_t>{_endAddress};
}
@ -132,6 +168,8 @@ Instruction::Calc::execute(AnalysisState &state) const {
state.current = _endAddress;
state.addKnownJump(getEndAddress(), getAddress(), JumpKind::Continue);
return std::vector<std::pair<uint32_t, std::unordered_map<uint32_t, uint32_t>>>();
}

View file

@ -57,6 +57,7 @@ namespace Instruction {
std::vector<uint8_t> toBytes() const override;
std::string toString() const override;
std::vector<OutputFormat> toOutputFormat(const OutputContext& context) const override;
std::vector<uint32_t> getPossibleBranches() const override;

View file

@ -92,6 +92,42 @@ std::string Instruction::CalcImm::toString() const {
return op.str();
}
std::vector<Instruction::OutputFormat> Instruction::CalcImm::toOutputFormat(const OutputContext &context) const {
std::stringstream opname;
switch (operation) {
case Calc::Operation::AND:
opname << "AND";
break;
case Calc::Operation::OR:
opname << "OR";
break;
case Calc::Operation::ADD:
opname << "ADD";
break;
case Calc::Operation::SUB:
opname << "SUB";
break;
case Calc::Operation::LSHIFT:
opname << "LSHIFT";
break;
case Calc::Operation::RSHIFT:
opname << "RSHIFT";
break;
case Calc::Operation::ARSHIFT:
opname << "ARSHIFT";
break;
case Calc::Operation::UNDEFINED:
opname << "UNDEFINED";
break;
}
return std::vector<OutputFormat>{
OutputFormat{getAddress(), dynamic_cast<std::stringstream&>(opname << "_IMM " << getAddressRegisterName(addressDestination, addressOffset) << " = ").str()},
OutputFormat{getAddress() + 4, dynamic_cast<std::stringstream&>(std::stringstream("") << " SOURCE " << getAddressRegisterName(addressSource, addressOffset)).str()},
OutputFormat{getAddress() + 8, dynamic_cast<std::stringstream&>(std::stringstream("") << " TARGET 0x" << value).str()},
};
}
std::vector<uint32_t> Instruction::CalcImm::getPossibleBranches() const {
return std::vector<uint32_t>{_endAddress};
}
@ -131,6 +167,8 @@ Instruction::CalcImm::execute(AnalysisState &state) const {
state.current = _endAddress;
state.addKnownJump(getEndAddress(), getAddress(), JumpKind::Continue);
return std::vector<std::pair<uint32_t, std::unordered_map<uint32_t, uint32_t>>>();
}

View file

@ -47,6 +47,7 @@ namespace Instruction {
std::vector<uint8_t> toBytes() const override;
std::string toString() const override;
std::vector<OutputFormat> toOutputFormat(const OutputContext& context) const override;
std::vector<uint32_t> getPossibleBranches() const override;

View file

@ -36,18 +36,18 @@ void Instruction::Copy::fromBytes(uint32_t offset, const std::vector<uint8_t> &b
uint32_t command = bytes[offset++];
count = (1 + ((command >> 4) & 0b11));
addressOffsetBB = (command >> 2) & 0b11;
addressOffsetAA = command & 0b11;
addressBB.offset = (command >> 2) & 0b11;
addressAA.offset = command & 0b11;
addressAA = bytes[offset++] << 16;
addressAA |= bytes[offset++] << 8;
addressAA |= bytes[offset++];
addressAA.address = bytes[offset++] << 16;
addressAA.address |= bytes[offset++] << 8;
addressAA.address |= bytes[offset++];
offset++;
addressBB = bytes[offset++] << 16;
addressBB |= bytes[offset++] << 8;
addressBB |= bytes[offset++];
addressBB.address = bytes[offset++] << 16;
addressBB.address |= bytes[offset++] << 8;
addressBB.address |= bytes[offset++];
_endAddress = offset;
@ -56,11 +56,18 @@ void Instruction::Copy::fromBytes(uint32_t offset, const std::vector<uint8_t> &b
std::string Instruction::Copy::toString() const {
std::stringstream op;
op << "COPY " << std::dec << (uint32_t) count << " WORDS FROM "
<< getAddressRegisterName(addressAA, addressOffsetAA) << " TO "
<< getAddressRegisterName(addressBB, addressOffsetBB);
<< getAddressRegisterName(addressAA) << " TO "
<< getAddressRegisterName(addressBB);
return op.str();
}
std::vector<Instruction::OutputFormat> Instruction::Copy::toOutputFormat(const OutputContext &context) const {
return std::vector<OutputFormat>{
OutputFormat{getAddress(), dynamic_cast<std::stringstream&>(std::stringstream("") << "COPY" << " " << std::dec << (uint32_t)count << ", " << getAddressRegisterName(addressAA)).str()},
OutputFormat{getAddress() + 4, dynamic_cast<std::stringstream&>(std::stringstream("") << " SOURCE " << getAddressRegisterName(addressBB)).str()}
};
}
std::vector<uint32_t> Instruction::Copy::getPossibleBranches() const {
return std::vector<uint32_t>{_endAddress};
}
@ -68,15 +75,14 @@ std::vector<uint32_t> Instruction::Copy::getPossibleBranches() const {
std::vector<std::pair<uint32_t, std::unordered_map<uint32_t, uint32_t>>>
Instruction::Copy::execute(AnalysisState &state) const {
uint32_t memoryOffsetAA = state.getAddressOffset(addressOffsetAA);
uint32_t memoryOffsetBB = state.getAddressOffset(addressOffsetBB);
for (uint32_t i = 0; i < count; ++i) {
state.setRegister(memoryOffsetAA + addressOffsetAA + i, state.getRegister(memoryOffsetBB + addressBB));
state.setRegister(addressAA.offset + addressAA.address + i, state.getRegister(addressBB.offset + addressBB.address + i));
}
state.current = _endAddress;
state.addKnownJump(getEndAddress(), getAddress(), JumpKind::Continue);
return std::vector<std::pair<uint32_t, std::unordered_map<uint32_t, uint32_t>>>();
}
@ -84,17 +90,17 @@ Instruction::Copy::execute(AnalysisState &state) const {
std::vector<uint8_t> Instruction::Copy::toBytes() const {
std::vector<uint8_t> bytes;
bytes.emplace_back((uint8_t) getCommand() | ((count - 1) << 4) | (addressOffsetBB << 2) | addressOffsetAA);
bytes.emplace_back((uint8_t) getCommand() | ((count - 1) << 4) | (addressBB.offset << 2) | addressAA.offset);
bytes.emplace_back((addressAA >> 16) & 0xFF);
bytes.emplace_back((addressAA >> 8) & 0xFF);
bytes.emplace_back(addressAA & 0xFF);
bytes.emplace_back((addressAA.address >> 16) & 0xFF);
bytes.emplace_back((addressAA.address >> 8) & 0xFF);
bytes.emplace_back(addressAA.address & 0xFF);
bytes.emplace_back(0);
bytes.emplace_back((addressBB >> 16) & 0xFF);
bytes.emplace_back((addressBB >> 8) & 0xFF);
bytes.emplace_back(addressBB & 0xFF);
bytes.emplace_back((addressBB.address >> 16) & 0xFF);
bytes.emplace_back((addressBB.address >> 8) & 0xFF);
bytes.emplace_back(addressBB.address & 0xFF);
return bytes;
}

View file

@ -45,6 +45,7 @@ namespace Instruction {
std::vector<uint8_t> toBytes() const override;
std::string toString() const override;
std::vector<OutputFormat> toOutputFormat(const OutputContext& context) const override;
std::vector<uint32_t> getPossibleBranches() const override;
@ -53,9 +54,7 @@ namespace Instruction {
uint8_t count;
uint8_t addressOffsetBB;
uint8_t addressOffsetAA;
uint32_t addressAA;
uint32_t addressBB;
AddressWithOffset addressAA;
AddressWithOffset addressBB;
};
}

View file

@ -26,6 +26,8 @@
*****************************************************************************/
#include "End.h"
#include <iostream>
#include <iomanip>
void Instruction::End::fromBytes(uint32_t offset, const std::vector<uint8_t> &bytes) {
_address = offset;
@ -43,6 +45,12 @@ std::string Instruction::End::toString() const {
return "END";
}
std::vector<Instruction::OutputFormat> Instruction::End::toOutputFormat(const OutputContext &context) const {
return std::vector<OutputFormat>{
OutputFormat{getAddress(), "END"}
};
}
std::vector<uint32_t> Instruction::End::getPossibleBranches() const {
return std::vector<uint32_t>();
}

View file

@ -45,6 +45,7 @@ namespace Instruction {
std::vector<uint8_t> toBytes() const override;
std::string toString() const override;
std::vector<OutputFormat> toOutputFormat(const OutputContext& context) const override;
std::vector<uint32_t> getPossibleBranches() const override;

View file

@ -77,6 +77,12 @@ std::string Instruction::Init::toString() const {
return op.str();
}
std::vector<Instruction::OutputFormat> Instruction::Init::toOutputFormat(const OutputContext &context) const {
return std::vector<OutputFormat>{
//TODO
};
}
std::vector<uint32_t> Instruction::Init::getPossibleBranches() const {
return std::vector<uint32_t>{_endAddress};
}
@ -89,6 +95,8 @@ Instruction::Init::execute(AnalysisState &state) const {
state.current = _endAddress;
state.addKnownJump(getEndAddress(), getAddress(), JumpKind::Continue);
return std::vector<std::pair<uint32_t, std::unordered_map<uint32_t, uint32_t>>>();
}

View file

@ -45,6 +45,7 @@ namespace Instruction {
std::vector<uint8_t> toBytes() const override;
std::string toString() const override;
std::vector<OutputFormat> toOutputFormat(const OutputContext& context) const override;
std::vector<uint32_t> getPossibleBranches() const override;

View file

@ -34,7 +34,13 @@
#include <memory>
#include "../AnalysisState.h"
class OutputContext;
namespace Instruction {
typedef struct{
uint32_t location;
std::string format;
} OutputFormat;
class Instruction {
protected:
@ -42,18 +48,6 @@ namespace Instruction {
uint32_t _endAddress{};
public:
/*Instruction(){
}
*/
/*
Instruction(const Instruction& instruction) : address(instruction.address), endAddress(instruction.endAddress), command(instruction.command), parameters(instruction.parameters){
}
*/
enum class CommandOp : uint8_t {
WRITE = 0b00000000,
COPY = 0b01000000,
@ -76,16 +70,12 @@ namespace Instruction {
static CommandOp getCommandFromByte(uint8_t command);
/*
Instruction(uint32_t address, uint32_t command, std::vector<uint32_t> parameters) : address(address), command(command), parameters(std::move(parameters)), endAddress(0){
}*/
virtual void fromBytes(uint32_t offset, const std::vector<uint8_t> &bytes) = 0;
virtual std::vector<uint8_t> toBytes() const = 0;
virtual std::string toString() const = 0;
virtual std::vector<OutputFormat> toOutputFormat(const OutputContext& context) const = 0;
virtual std::vector<uint32_t> getPossibleBranches() const = 0;

View file

@ -29,6 +29,7 @@
#include "../Registers.h"
#include <iostream>
#include <iomanip>
#include "../OutputContext.h"
void Instruction::Jump::fromBytes(uint32_t offset, const std::vector<uint8_t> &bytes) {
_address = offset;
@ -50,6 +51,12 @@ std::string Instruction::Jump::toString() const {
return op.str();
}
std::vector<Instruction::OutputFormat> Instruction::Jump::toOutputFormat(const OutputContext &context) const {
return std::vector<OutputFormat>{
OutputFormat{getAddress(), dynamic_cast<std::stringstream&>(std::stringstream("") << "JUMP" << " " << context.getLabel(jumpAddress)).str()}
};
}
std::vector<uint32_t> Instruction::Jump::getPossibleBranches() const {
return std::vector<uint32_t>{jumpAddress};
}
@ -58,6 +65,8 @@ std::vector<std::pair<uint32_t, std::unordered_map<uint32_t, uint32_t>>>
Instruction::Jump::execute(AnalysisState &state) const {
state.current = jumpAddress;
state.addKnownJump(jumpAddress, getAddress(), JumpKind::Absolute);
return std::vector<std::pair<uint32_t, std::unordered_map<uint32_t, uint32_t>>>();
}

View file

@ -45,6 +45,7 @@ namespace Instruction {
std::vector<uint8_t> toBytes() const override;
std::string toString() const override;
std::vector<OutputFormat> toOutputFormat(const OutputContext& context) const override;
std::vector<uint32_t> getPossibleBranches() const override;

View file

@ -29,6 +29,7 @@
#include "../Registers.h"
#include <iostream>
#include <iomanip>
#include "../OutputContext.h"
void Instruction::Load::fromBytes(uint32_t offset, const std::vector<uint8_t> &bytes) {
_address = offset;
@ -111,6 +112,59 @@ std::string Instruction::Load::toString() const {
return op.str();
}
std::vector<Instruction::OutputFormat> Instruction::Load::toOutputFormat(const OutputContext &context) const {
if (addressOffset == 0 && increment == 0 &&
address == (uint32_t) KnownRegisters::PCIE_MASTER_SPICO_FIRMWARE_SPECIAL_REGISTER) {
uint32_t offset = 0;
std::vector<OutputFormat> f{
OutputFormat{getAddress() + offset++ * 4, dynamic_cast<std::stringstream&>(std::stringstream("") << "LOAD" << " PCIE_MASTER_SPICO_FIRMWARE").str()}
};
f.emplace_back(OutputFormat{getAddress() + offset++ * 4, dynamic_cast<std::stringstream&>(std::stringstream("") << " COUNT " << std::dec << data.size()).str()});
for (auto d : data) {
f.emplace_back(OutputFormat{getAddress() + offset * 4, dynamic_cast<std::stringstream&>(std::stringstream("") << " " << " = 0x" << std::hex << std::setw(8) << std::setfill('0') << d).str()});
offset++;
}
return f;
} else if (addressOffset == 0 && increment == 0 &&
address == (uint32_t) KnownRegisters::PCIE_BROADCAST_SERDES_FIRMWARE_SPECIAL_REGISTER) {
uint32_t offset = 0;
std::vector<OutputFormat> f{
OutputFormat{getAddress() + offset++ * 4, dynamic_cast<std::stringstream&>(std::stringstream("") << "LOAD" << " PCIE_BROADCAST_SERDES_FIRMWARE").str()},
};
f.emplace_back(OutputFormat{getAddress() + offset++ * 4, dynamic_cast<std::stringstream&>(std::stringstream("") << " COUNT " << std::dec << data.size()).str()});
for (auto d : data) {
f.emplace_back(OutputFormat{getAddress() + offset * 4, dynamic_cast<std::stringstream&>(std::stringstream("") << " " << " = 0x" << std::hex << std::setw(8) << std::setfill('0') << d).str()});
offset++;
}
return f;
}else{
uint32_t offset = 0;
std::vector<OutputFormat> f{
OutputFormat{getAddress() + offset++ * 4, dynamic_cast<std::stringstream&>(std::stringstream("") << "LOAD" << " " << getAddressRegisterName(address, addressOffset) << ", INC " << std::dec << (uint32_t)increment).str()}
};
f.emplace_back(OutputFormat{getAddress() + offset++ * 4, dynamic_cast<std::stringstream&>(std::stringstream("") << " COUNT " << std::dec << data.size()).str()});
for (auto d : data) {
f.emplace_back(OutputFormat{getAddress() + offset * 4, dynamic_cast<std::stringstream&>(std::stringstream("") << " " << getAddressRegisterName(address + offset - 1, addressOffset) << " = 0x" << std::hex << std::setw(8) << std::setfill('0') << d).str()});
offset++;
}
return f;
}
}
std::vector<uint32_t> Instruction::Load::getPossibleBranches() const {
return std::vector<uint32_t>{_endAddress};
}
@ -132,9 +186,10 @@ Instruction::Load::execute(AnalysisState &state) const {
state.current = _endAddress;
state.addKnownJump(getEndAddress(), getAddress(), JumpKind::Continue);
return std::vector<std::pair<uint32_t, std::unordered_map<uint32_t, uint32_t>>>();
}
std::vector<uint8_t> Instruction::Load::toBytes() const {
std::vector<uint8_t> bytes;

View file

@ -45,6 +45,7 @@ namespace Instruction {
std::vector<uint8_t> toBytes() const override;
std::string toString() const override;
std::vector<OutputFormat> toOutputFormat(const OutputContext& context) const override;
std::vector<uint32_t> getPossibleBranches() const override;

View file

@ -29,6 +29,7 @@
#include "../Registers.h"
#include <iostream>
#include <iomanip>
#include "../OutputContext.h"
void Instruction::Loop::fromBytes(uint32_t offset, const std::vector<uint8_t> &bytes) {
_address = offset;
@ -52,6 +53,12 @@ std::string Instruction::Loop::toString() const {
return op.str();
}
std::vector<Instruction::OutputFormat> Instruction::Loop::toOutputFormat(const OutputContext &context) const {
return std::vector<OutputFormat>{
OutputFormat{getAddress(), dynamic_cast<std::stringstream&>(std::stringstream("") << "LOOP" << " " << getRegisterName(static_cast<KnownRegisters>((uint32_t) KnownRegisters::BSM_COUNTER_0 + counter)) << ", " << context.getLabel(jumpAddress)).str()},
};
}
std::vector<uint32_t> Instruction::Loop::getPossibleBranches() const {
return std::vector<uint32_t>{_endAddress, jumpAddress};
}
@ -77,6 +84,9 @@ Instruction::Loop::execute(AnalysisState &state) const {
branches.emplace_back(_endAddress, std::move(branchedState));
}
state.addKnownJump(getEndAddress(), getAddress(), JumpKind::Continue);
state.addKnownJump(jumpAddress, getAddress(), JumpKind::Loop);
return branches;
}

View file

@ -45,6 +45,7 @@ namespace Instruction {
std::vector<uint8_t> toBytes() const override;
std::string toString() const override;
std::vector<OutputFormat> toOutputFormat(const OutputContext& context) const override;
std::vector<uint32_t> getPossibleBranches() const override;

View file

@ -29,6 +29,7 @@
#include "../Registers.h"
#include <iostream>
#include <iomanip>
#include "../OutputContext.h"
void Instruction::Poll::fromBytes(uint32_t offset, const std::vector<uint8_t> &bytes) {
_address = offset;
@ -84,6 +85,16 @@ std::string Instruction::Poll::toString() const {
return op.str();
}
std::vector<Instruction::OutputFormat> Instruction::Poll::toOutputFormat(const OutputContext &context) const {
return std::vector<OutputFormat>{
OutputFormat{getAddress(), dynamic_cast<std::stringstream&>(std::stringstream("") << "POLL" << " " << getAddressRegisterName(address, addressOffset) << (equality ? " == " : " != ")).str()},
OutputFormat{getAddress() + 4, dynamic_cast<std::stringstream&>(std::stringstream("") << " VALUE 0x" << std::hex << std::setw(8) << std::setfill('0') << value).str()},
OutputFormat{getAddress() + 8, dynamic_cast<std::stringstream&>(std::stringstream("") << " MASK 0x" << std::hex << std::setw(8) << std::setfill('0') << mask).str()},
OutputFormat{getAddress() + 12, dynamic_cast<std::stringstream&>(std::stringstream("") << " RETRY MAX " << std::dec << maxRetry << " INTERVAL " << std::dec << retryInterval).str()},
OutputFormat{getAddress() + 16, dynamic_cast<std::stringstream&>(std::stringstream("") << " JUMP_ADDRESS " << context.getLabel(jumpAddress)).str()},
};
}
std::vector<uint32_t> Instruction::Poll::getPossibleBranches() const {
return std::vector<uint32_t>{_endAddress, jumpAddress};
}
@ -110,6 +121,9 @@ Instruction::Poll::execute(AnalysisState &state) const {
branches.emplace_back(equality ? _endAddress : jumpAddress, std::move(branchedState));
}
state.addKnownJump(getEndAddress(), getAddress(), JumpKind::Continue);
state.addKnownJump(jumpAddress, getAddress(), JumpKind::Branch);
return branches;
}

View file

@ -45,6 +45,7 @@ namespace Instruction {
std::vector<uint8_t> toBytes() const override;
std::string toString() const override;
std::vector<OutputFormat> toOutputFormat(const OutputContext& context) const override;
std::vector<uint32_t> getPossibleBranches() const override;

View file

@ -35,11 +35,11 @@ void Instruction::Return::fromBytes(uint32_t offset, const std::vector<uint8_t>
uint8_t command = bytes[offset++];
addressOffset = command & 0b11;
address.offset = command & 0b11;
address = bytes[offset++] << 16;
address |= bytes[offset++] << 8;
address |= bytes[offset++];
address.address = bytes[offset++] << 16;
address.address |= bytes[offset++] << 8;
address.address |= bytes[offset++];
_endAddress = offset;
@ -47,22 +47,28 @@ void Instruction::Return::fromBytes(uint32_t offset, const std::vector<uint8_t>
std::string Instruction::Return::toString() const {
std::stringstream op;
op << "RETURN " << getAddressRegisterName(address, addressOffset);
op << "RETURN " << getAddressRegisterName(address);
return op.str();
}
std::vector<Instruction::OutputFormat> Instruction::Return::toOutputFormat(const OutputContext &context) const {
return std::vector<OutputFormat>{
OutputFormat{getAddress(), dynamic_cast<std::stringstream&>(std::stringstream("") << "RETURN" << " [" << getAddressRegisterName(address) << "]").str()}
};
}
std::vector<uint32_t> Instruction::Return::getPossibleBranches() const {
return std::vector<uint32_t>();
}
std::vector<std::pair<uint32_t, std::unordered_map<uint32_t, uint32_t>>>
Instruction::Return::execute(AnalysisState &state) const {
uint32_t memoryOffset = state.getAddressOffset(addressOffset);
uint32_t jumpAddress = state.getRegister(memoryOffset + address);
uint32_t jumpAddress = state.getRegister(address);
state.current = jumpAddress;
state.addKnownJump(jumpAddress, getAddress(), JumpKind::Return);
return std::vector<std::pair<uint32_t, std::unordered_map<uint32_t, uint32_t>>>();
}
@ -70,11 +76,11 @@ Instruction::Return::execute(AnalysisState &state) const {
std::vector<uint8_t> Instruction::Return::toBytes() const {
std::vector<uint8_t> bytes;
bytes.emplace_back((uint8_t) getCommand() | addressOffset);
bytes.emplace_back((uint8_t) getCommand() | address.offset);
bytes.emplace_back((address >> 16) & 0xFF);
bytes.emplace_back((address >> 8) & 0xFF);
bytes.emplace_back(address & 0xFF);
bytes.emplace_back((address.address >> 16) & 0xFF);
bytes.emplace_back((address.address >> 8) & 0xFF);
bytes.emplace_back(address.address & 0xFF);
return bytes;
}

View file

@ -45,13 +45,13 @@ namespace Instruction {
std::vector<uint8_t> toBytes() const override;
std::string toString() const override;
std::vector<OutputFormat> toOutputFormat(const OutputContext& context) const override;
std::vector<uint32_t> getPossibleBranches() const override;
std::vector<std::pair<uint32_t, std::unordered_map<uint32_t, uint32_t>>>
execute(AnalysisState &state) const override;
uint8_t addressOffset;
uint32_t address;
AddressWithOffset address;
};
}

View file

@ -35,11 +35,11 @@ void Instruction::Set::fromBytes(uint32_t offset, const std::vector<uint8_t> &by
uint8_t command = bytes[offset++];
addressOffset = command & 0b11;
address.offset = command & 0b11;
address = bytes[offset++] << 16;
address |= bytes[offset++] << 8;
address |= bytes[offset++];
address.address = bytes[offset++] << 16;
address.address |= bytes[offset++] << 8;
address.address |= bytes[offset++];
value = bytes[offset++] << 24;
value |= bytes[offset++] << 16;
@ -57,35 +57,43 @@ void Instruction::Set::fromBytes(uint32_t offset, const std::vector<uint8_t> &by
std::string Instruction::Set::toString() const {
std::stringstream op;
op << "SET " << getAddressRegisterName(address, addressOffset) << " = ("
<< getAddressRegisterName(address, addressOffset) << " & ~0x" << std::hex << std::setw(8) << std::setfill('0')
op << "SET " << getAddressRegisterName(address) << " = ("
<< getAddressRegisterName(address) << " & ~0x" << std::hex << std::setw(8) << std::setfill('0')
<< mask << ") | " << "0x" << std::hex << std::setw(8) << std::setfill('0') << value;
return op.str();
}
std::vector<Instruction::OutputFormat> Instruction::Set::toOutputFormat(const OutputContext &context) const {
return std::vector<OutputFormat>{
OutputFormat{getAddress(), dynamic_cast<std::stringstream&>(std::stringstream("") << "SET" << " " << getAddressRegisterName(address)).str()},
OutputFormat{getAddress() + 4, dynamic_cast<std::stringstream&>(std::stringstream("") << " VALUE 0x" << std::hex << std::setw(8) << std::setfill('0') << value).str()},
OutputFormat{getAddress() + 8, dynamic_cast<std::stringstream&>(std::stringstream("") << " MASK 0x" << std::hex << std::setw(8) << std::setfill('0') << mask).str()}
};
}
std::vector<uint32_t> Instruction::Set::getPossibleBranches() const {
return std::vector<uint32_t>{_endAddress};
}
std::vector<std::pair<uint32_t, std::unordered_map<uint32_t, uint32_t>>>
Instruction::Set::execute(AnalysisState &state) const {
uint32_t memoryOffset = state.getAddressOffset(addressOffset);
state.setRegister(memoryOffset + address, (state.getRegister(memoryOffset + address) & ~mask) | value);
state.setRegister(address, (state.getRegister(address) & ~mask) | value);
state.current = _endAddress;
state.addKnownJump(getEndAddress(), getAddress(), JumpKind::Continue);
return std::vector<std::pair<uint32_t, std::unordered_map<uint32_t, uint32_t>>>();
}
std::vector<uint8_t> Instruction::Set::toBytes() const {
std::vector<uint8_t> bytes;
bytes.emplace_back((uint8_t) getCommand() | addressOffset);
bytes.emplace_back((uint8_t) getCommand() | address.offset);
bytes.emplace_back((address >> 16) & 0xFF);
bytes.emplace_back((address >> 8) & 0xFF);
bytes.emplace_back(address & 0xFF);
bytes.emplace_back((address.address >> 16) & 0xFF);
bytes.emplace_back((address.address >> 8) & 0xFF);
bytes.emplace_back(address.address & 0xFF);
bytes.emplace_back((value >> 24) & 0xFF);
bytes.emplace_back((value >> 16) & 0xFF);

View file

@ -45,14 +45,14 @@ namespace Instruction {
std::vector<uint8_t> toBytes() const override;
std::string toString() const override;
std::vector<OutputFormat> toOutputFormat(const OutputContext& context) const override;
std::vector<uint32_t> getPossibleBranches() const override;
std::vector<std::pair<uint32_t, std::unordered_map<uint32_t, uint32_t>>>
execute(AnalysisState &state) const override;
uint8_t addressOffset;
uint32_t address;
AddressWithOffset address;
uint32_t value;
uint32_t mask;
};

View file

@ -50,6 +50,12 @@ std::string Instruction::Wait::toString() const {
return op.str();
}
std::vector<Instruction::OutputFormat> Instruction::Wait::toOutputFormat(const OutputContext &context) const {
return std::vector<OutputFormat>{
OutputFormat{getAddress(), dynamic_cast<std::stringstream&>(std::stringstream("") << "WAIT" << " " << std::dec << time).str()}
};
}
std::vector<uint32_t> Instruction::Wait::getPossibleBranches() const {
return std::vector<uint32_t>{_endAddress};
}
@ -60,6 +66,8 @@ Instruction::Wait::execute(AnalysisState &state) const {
state.current = _endAddress;
state.addKnownJump(getEndAddress(), getAddress(), JumpKind::Continue);
return std::vector<std::pair<uint32_t, std::unordered_map<uint32_t, uint32_t>>>();
}

View file

@ -45,6 +45,7 @@ namespace Instruction {
std::vector<uint8_t> toBytes() const override;
std::string toString() const override;
std::vector<OutputFormat> toOutputFormat(const OutputContext& context) const override;
std::vector<uint32_t> getPossibleBranches() const override;

View file

@ -29,6 +29,7 @@
#include "../Registers.h"
#include <iostream>
#include <iomanip>
#include "../OutputContext.h"
void Instruction::Write::fromBytes(uint32_t offset, const std::vector<uint8_t> &bytes) {
_address = offset;
@ -64,6 +65,22 @@ std::string Instruction::Write::toString() const {
return op.str();
}
std::vector<Instruction::OutputFormat> Instruction::Write::toOutputFormat(const OutputContext &context) const {
uint32_t offset = 0;
std::vector<OutputFormat> f{
OutputFormat{getAddress() + offset++ * 4, dynamic_cast<std::stringstream&>(std::stringstream("") << "WRITE" << " " << getAddressRegisterName(address, addressOffset) << ", " << std::dec << (uint32_t ) data.size()).str()}
};
for (auto d : data) {
f.emplace_back(OutputFormat{getAddress() + offset * 4, dynamic_cast<std::stringstream&>(std::stringstream("") << " " << getAddressRegisterName(address + offset - 1, addressOffset) << " = 0x" << std::hex << std::setw(8) << std::setfill('0') << d).str()});
offset++;
}
return f;
}
std::vector<uint32_t> Instruction::Write::getPossibleBranches() const {
return std::vector<uint32_t>{_endAddress};
}
@ -78,6 +95,10 @@ Instruction::Write::execute(AnalysisState &state) const {
state.current = _endAddress;
state.addKnownJump(getEndAddress(), getAddress(), JumpKind::Continue);
state.addKnownJump(getEndAddress(), getAddress(), JumpKind::Continue);
return std::vector<std::pair<uint32_t, std::unordered_map<uint32_t, uint32_t>>>();
}

View file

@ -34,12 +34,6 @@
namespace Instruction {
class Write : public Instruction {
public:
Write(uint32_t address, uint8_t addressOffset, std::vector<uint32_t> data) : address(address),
addressOffset(addressOffset),
data(std::move(data)) {
}
Write() {
}
@ -53,6 +47,7 @@ namespace Instruction {
std::vector<uint8_t> toBytes() const override;
std::string toString() const override;
std::vector<OutputFormat> toOutputFormat(const OutputContext& context) const override;
std::vector<uint32_t> getPossibleBranches() const override;

View file

@ -33,6 +33,7 @@
#include "ImageFormat.h"
#include "Registers.h"
#include "instructions/Load.h"
#include "OutputContext.h"
void decodeImage(const std::string &fileName) {
@ -54,6 +55,9 @@ void decodeImage(const std::string &fileName) {
std::cout << k << "\n";
}
OutputContext ctx(imageObject);
ctx.analyze();
uint32_t prevAddress = 0;
for (const auto &entry : imageObject.getInstructions()) {
const auto &instruction = entry.second;
@ -63,12 +67,13 @@ void decodeImage(const std::string &fileName) {
<< instruction->getAddress() << "\n";
} else if ((instruction->getAddress() - prevAddress) >= 4 &&
(instruction->getAddress() - prevAddress) < 1024) {
std::cout << "\n\n";
for (uint32_t addr = prevAddress; addr < instruction->getAddress(); addr += 4) {
std::stringstream op;
std::string printable;
op << std::hex << std::setw(8) << std::setfill('0') << addr << ": ";
op << std::hex << std::setw(6) << std::setfill('0') << addr << " ";
for (uint32_t i = 0; i < 4; ++i) {
op << std::hex << std::setw(2) << std::setfill('0') << (uint32_t) bytes[addr + i];
op << std::hex << std::setw(2) << std::setfill('0') << (uint32_t) bytes[addr + i] << " ";
if (bytes[addr + i] >= 0x20 && bytes[addr + i] < 0x7F) {
printable += bytes[addr + i];
} else {
@ -84,8 +89,12 @@ void decodeImage(const std::string &fileName) {
<< " - " << std::hex << std::setw(8) << std::setfill('0') << instruction->getAddress()
<< "\n";
}
std::cout << std::hex << std::setw(8) << std::setfill('0') << instruction->getAddress() << ": ";
std::cout << instruction->toString() << "\n";
if(!ctx.getLabel(instruction->getAddress(), false).empty()){
std::cout << "\n\n; == FUNCTION " << ctx.getLabel(instruction->getAddress()) << " ==\n";
}
std::cout << ctx.getInstructionString(*instruction);
prevAddress = instruction->getEndAddress();
}
}