Create tagged assembly, context, and known jump table. Split "decode" output into functions
This commit is contained in:
parent
58b55c20ce
commit
88e7f0d8b8
|
@ -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})
|
||||
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
};
|
|
@ -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);
|
||||
}
|
||||
|
||||
|
|
|
@ -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
124
src/OutputContext.cpp
Normal 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
77
src/OutputContext.h
Normal 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();
|
||||
};
|
|
@ -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);
|
||||
}
|
|
@ -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);
|
35
src/instructions/AddressOffset.h
Normal file
35
src/instructions/AddressOffset.h
Normal 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;
|
||||
}
|
|
@ -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);
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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>>>();
|
||||
}
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
||||
|
|
|
@ -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>>>();
|
||||
}
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
};
|
||||
}
|
|
@ -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>();
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
|
||||
|
|
|
@ -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>>>();
|
||||
}
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
||||
|
|
|
@ -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>>>();
|
||||
}
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
||||
|
|
|
@ -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;
|
||||
}
|
|
@ -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;
|
||||
};
|
||||
}
|
|
@ -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);
|
||||
|
|
|
@ -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;
|
||||
};
|
||||
|
|
|
@ -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>>>();
|
||||
}
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
||||
|
|
|
@ -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>>>();
|
||||
}
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
||||
|
|
17
src/main.cpp
17
src/main.cpp
|
@ -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();
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue