mirror of
https://github.com/TomHarte/CLK.git
synced 2024-06-25 18:30:07 +00:00
Makes first efforts towards disassembly.
This commit is contained in:
parent
cc90935abd
commit
56111c75ae
|
@ -9,6 +9,8 @@
|
|||
#ifndef CachingExecutor_hpp
|
||||
#define CachingExecutor_hpp
|
||||
|
||||
#include "Sizes.hpp"
|
||||
|
||||
#include <array>
|
||||
#include <cstdint>
|
||||
#include <limits>
|
||||
|
@ -19,29 +21,6 @@
|
|||
|
||||
namespace InstructionSet {
|
||||
|
||||
/*!
|
||||
Maps to the smallest of the following integers that can contain max_value:
|
||||
|
||||
* uint8_t;
|
||||
* uint16_t;
|
||||
* uint32_t; or
|
||||
* uint64_t.
|
||||
*/
|
||||
template <uint64_t max_value> struct MinIntTypeValue {
|
||||
using type =
|
||||
std::conditional_t<
|
||||
max_value <= std::numeric_limits<uint8_t>::max(), uint8_t,
|
||||
std::conditional_t<
|
||||
max_value <= std::numeric_limits<uint16_t>::max(), uint16_t,
|
||||
std::conditional_t<
|
||||
max_value <= std::numeric_limits<uint32_t>::max(), uint32_t,
|
||||
uint64_t
|
||||
>
|
||||
>
|
||||
>;
|
||||
};
|
||||
|
||||
|
||||
/*!
|
||||
A caching executor makes use of an instruction set-specific executor to cache 'performers' (i.e. function pointers)
|
||||
that result from decoding.
|
||||
|
|
80
InstructionSets/Disassembler.hpp
Normal file
80
InstructionSets/Disassembler.hpp
Normal file
|
@ -0,0 +1,80 @@
|
|||
//
|
||||
// Disassembler.hpp
|
||||
// Clock Signal
|
||||
//
|
||||
// Created by Thomas Harte on 26/01/2021.
|
||||
// Copyright © 2021 Thomas Harte. All rights reserved.
|
||||
//
|
||||
|
||||
#ifndef Disassembler_hpp
|
||||
#define Disassembler_hpp
|
||||
|
||||
#include "Sizes.hpp"
|
||||
|
||||
#include <list>
|
||||
#include <map>
|
||||
#include <set>
|
||||
|
||||
namespace InstructionSet {
|
||||
|
||||
template <
|
||||
/// Indicates the Parser for this platform.
|
||||
template<typename, bool> class ParserType,
|
||||
/// Indicates the greatest value the program counter might take.
|
||||
uint64_t max_address,
|
||||
/// Provides the type of Instruction to expect.
|
||||
typename InstructionType,
|
||||
/// Provides the storage size used for memory.
|
||||
typename MemoryWord,
|
||||
/// Provides the addressing range of memory.
|
||||
typename AddressType
|
||||
> class Disassembler {
|
||||
public:
|
||||
using ProgramCounterType = typename MinIntTypeValue<max_address>::type;
|
||||
static_assert(!std::is_same_v<ProgramCounterType, void>);
|
||||
|
||||
/*!
|
||||
Adds the result of disassembling @c memory which is @c length @c MemoryWords long from @c start_address
|
||||
to the current net total of instructions and recorded memory accesses.
|
||||
*/
|
||||
void disassemble(const MemoryWord *memory, ProgramCounterType location, ProgramCounterType length, ProgramCounterType start_address) {
|
||||
// TODO: possibly, move some of this stuff to instruction-set specific disassemblers, analogous to
|
||||
// the Executor's ownership of the Parser. That would allow handling of stateful parsing.
|
||||
ParserType<decltype(*this), true> parser;
|
||||
pending_entry_points_.push_back(start_address);
|
||||
entry_points_.insert(start_address);
|
||||
|
||||
while(!pending_entry_points_.empty()) {
|
||||
const auto next_entry_point = pending_entry_points_.front();
|
||||
pending_entry_points_.pop_front();
|
||||
|
||||
parser.parse(*this, memory - location, next_entry_point, length + location);
|
||||
}
|
||||
}
|
||||
|
||||
void announce_overflow(ProgramCounterType) {}
|
||||
void announce_instruction(ProgramCounterType address, InstructionType instruction) {
|
||||
instructions_[address] = instruction;
|
||||
}
|
||||
void add_entry(ProgramCounterType address) {
|
||||
if(entry_points_.find(address) == entry_points_.end()) {
|
||||
pending_entry_points_.push_back(address);
|
||||
entry_points_.insert(address);
|
||||
}
|
||||
}
|
||||
void add_access(AddressType address, AccessType access_type) {
|
||||
// TODO.
|
||||
(void)address;
|
||||
(void)access_type;
|
||||
}
|
||||
|
||||
private:
|
||||
std::map<ProgramCounterType, InstructionType> instructions_;
|
||||
std::set<ProgramCounterType> entry_points_;
|
||||
|
||||
std::list<ProgramCounterType> pending_entry_points_;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif /* Disassembler_h */
|
34
InstructionSets/Sizes.hpp
Normal file
34
InstructionSets/Sizes.hpp
Normal file
|
@ -0,0 +1,34 @@
|
|||
//
|
||||
// Sizes.hpp
|
||||
// Clock Signal
|
||||
//
|
||||
// Created by Thomas Harte on 26/01/2021.
|
||||
// Copyright © 2021 Thomas Harte. All rights reserved.
|
||||
//
|
||||
|
||||
#ifndef Sizes_h
|
||||
#define Sizes_h
|
||||
|
||||
/*!
|
||||
Maps to the smallest of the following integers that can contain max_value:
|
||||
|
||||
* uint8_t;
|
||||
* uint16_t;
|
||||
* uint32_t; or
|
||||
* uint64_t.
|
||||
*/
|
||||
template <uint64_t max_value> struct MinIntTypeValue {
|
||||
using type =
|
||||
std::conditional_t<
|
||||
max_value <= std::numeric_limits<uint8_t>::max(), uint8_t,
|
||||
std::conditional_t<
|
||||
max_value <= std::numeric_limits<uint16_t>::max(), uint16_t,
|
||||
std::conditional_t<
|
||||
max_value <= std::numeric_limits<uint32_t>::max(), uint32_t,
|
||||
uint64_t
|
||||
>
|
||||
>
|
||||
>;
|
||||
};
|
||||
|
||||
#endif /* Sizes_h */
|
|
@ -11,6 +11,10 @@
|
|||
#include <cassert>
|
||||
#include <cstdio>
|
||||
|
||||
// TEST.
|
||||
#include "../../../InstructionSets/M50740/Parser.hpp"
|
||||
#include "../../../InstructionSets/Disassembler.hpp"
|
||||
|
||||
using namespace Apple::IIgs::ADB;
|
||||
|
||||
GLU::GLU() : executor_(*this) {}
|
||||
|
@ -217,6 +221,9 @@ uint8_t GLU::read_microcontroller_address(uint16_t address) {
|
|||
|
||||
void GLU::set_microcontroller_rom(const std::vector<uint8_t> &rom) {
|
||||
executor_.set_rom(rom);
|
||||
|
||||
InstructionSet::Disassembler<InstructionSet::M50740::Parser, 0x1fff, InstructionSet::M50740::Instruction, uint8_t, uint16_t> disassembler;
|
||||
disassembler.disassemble(rom.data(), 0x1000, uint16_t(rom.size()), 0x1000);
|
||||
}
|
||||
|
||||
void GLU::run_for(Cycles cycles) {
|
||||
|
|
|
@ -1914,6 +1914,8 @@
|
|||
4BE34437238389E10058E78F /* AtariSTVideoTests.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = AtariSTVideoTests.mm; sourceTree = "<group>"; };
|
||||
4BE76CF822641ED300ACD6FA /* QLTests.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = QLTests.mm; sourceTree = "<group>"; };
|
||||
4BE845201F2FF7F100A5EA22 /* CRTC6845.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; name = CRTC6845.hpp; path = 6845/CRTC6845.hpp; sourceTree = "<group>"; };
|
||||
4BE8EB5425C0E9D40040BC40 /* Disassembler.hpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.h; path = Disassembler.hpp; sourceTree = "<group>"; };
|
||||
4BE8EB5525C0EA490040BC40 /* Sizes.hpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.h; path = Sizes.hpp; sourceTree = "<group>"; };
|
||||
4BE90FFC22D5864800FB464D /* MacintoshVideoTests.mm */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.objcpp; path = MacintoshVideoTests.mm; sourceTree = "<group>"; };
|
||||
4BE9A6B01EDE293000CBCB47 /* zexdoc.com */ = {isa = PBXFileReference; lastKnownFileType = file; name = zexdoc.com; path = Zexall/zexdoc.com; sourceTree = "<group>"; };
|
||||
4BEA525D1DF33323007E74F2 /* Tape.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = Tape.cpp; path = Electron/Tape.cpp; sourceTree = "<group>"; };
|
||||
|
@ -4352,6 +4354,8 @@
|
|||
children = (
|
||||
4BEDA42925B3C26B000C2DBD /* AccessType.hpp */,
|
||||
4BEDA45425B5ECAB000C2DBD /* CachingExecutor.hpp */,
|
||||
4BE8EB5425C0E9D40040BC40 /* Disassembler.hpp */,
|
||||
4BE8EB5525C0EA490040BC40 /* Sizes.hpp */,
|
||||
4BEDA3B625B25563000C2DBD /* README.md */,
|
||||
4BEDA40925B2844B000C2DBD /* M50740 */,
|
||||
4BEDA3B325B25563000C2DBD /* PowerPC */,
|
||||
|
|
Loading…
Reference in New Issue
Block a user