1
0
mirror of https://github.com/TomHarte/CLK.git synced 2024-06-17 21:30:14 +00:00

Begin foray into disassembly.

This commit is contained in:
Thomas Harte 2024-03-19 11:34:10 -04:00
parent 9d858bc61b
commit 2ad6bb099b
5 changed files with 152 additions and 10 deletions

View File

@ -0,0 +1,119 @@
//
// Disassembler.hpp
// Clock Signal
//
// Created by Thomas Harte on 19/03/2024.
// Copyright © 2024 Thomas Harte. All rights reserved.
//
#pragma once
#include "OperationMapper.hpp"
#include <string>
#include <sstream>
namespace InstructionSet::ARM {
struct Operand {
enum class Type {
Immediate, Register, RegisterList,
} type = Type::Immediate;
uint32_t value = 0;
// TODO: encode shifting
operator std::string() const {
return "";
}
};
struct Instruction {
Condition condition;
enum class Operation {
AND, EOR, SUB, RSB,
ADD, ADC, SBC, RSC,
TST, TEQ, CMP, CMN,
ORR, MOV, BIC, MVN,
B, BL,
SWI,
Undefined,
} operation = Operation::Undefined;
Operand destination, operand1, operand2;
std::string to_string(uint32_t address) const {
std::string result;
// Print operation.
switch(operation) {
case Operation::Undefined: return "undefined";
case Operation::SWI: return "swi";
case Operation::B: result += "b"; break;
case Operation::BL: result += "bl"; break;
case Operation::AND: result += "and"; break;
case Operation::EOR: result += "eor"; break;
case Operation::SUB: result += "sub"; break;
case Operation::RSB: result += "rsb"; break;
case Operation::ADD: result += "add"; break;
case Operation::ADC: result += "adc"; break;
case Operation::SBC: result += "sbc"; break;
case Operation::RSC: result += "rsc"; break;
case Operation::TST: result += "tst"; break;
case Operation::TEQ: result += "teq"; break;
case Operation::CMP: result += "cmp"; break;
case Operation::CMN: result += "cmn"; break;
case Operation::ORR: result += "orr"; break;
case Operation::MOV: result += "mov"; break;
case Operation::BIC: result += "bic"; break;
case Operation::MVN: result += "mvn"; break;
}
// If this is a branch, append the target and complete.
if(operation == Operation::B || operation == Operation::BL) {
result += " ";
}
return result;
}
};
template <Model model>
struct Disassembler {
Instruction last() {
return instruction_;
}
bool should_schedule(Condition condition) {
instruction_.condition = condition;
return true;
}
template <Flags> void perform(DataProcessing) {}
template <Flags> void perform(Multiply) {}
template <Flags> void perform(SingleDataTransfer) {}
template <Flags> void perform(BlockDataTransfer) {}
template <Flags> void perform(Branch) {}
template <Flags> void perform(CoprocessorRegisterTransfer) {}
template <Flags> void perform(CoprocessorDataOperation) {}
template <Flags> void perform(CoprocessorDataTransfer) {}
void software_interrupt() {
instruction_.operation = Instruction::Operation::SWI;
}
void unknown() {
instruction_.operation = Instruction::Operation::Undefined;
}
private:
Instruction instruction_;
};
}

View File

@ -14,6 +14,7 @@
#include "../../ScanProducer.hpp"
#include "../../TimedMachine.hpp"
#include "../../../InstructionSets/ARM/Disassembler.hpp"
#include "../../../InstructionSets/ARM/Executor.hpp"
#include "../../../Outputs/Log.hpp"
#include "../../../Components/I2C/I2C.hpp"
@ -1043,9 +1044,14 @@ class ConcreteMachine:
return Outputs::Display::ScanStatus();
}
std::array<uint32_t, 10> pc_history;
std::size_t pc_history_ptr = 0;
uint32_t instr_count = 0;
// MARK: - TimedMachine.
void run_for(Cycles cycles) override {
static uint32_t last_pc = 0;
static bool log = true;
auto instructions = cycles.as<int>();
@ -1055,11 +1061,10 @@ class ConcreteMachine:
timer_divider_ -= run_length;
while(run_length--) {
if(executor_.pc() == 0x0207b3bc) {
printf("At %08x after last PC %08x\n", executor_.pc(), last_pc);
}
uint32_t instruction;
pc_history[pc_history_ptr] = executor_.pc();
pc_history_ptr = (pc_history_ptr + 1) % pc_history.size();
// pc_history.push_back(executor_.pc());
if(!executor_.bus.read(executor_.pc(), instruction, executor_.registers().mode(), false)) {
logger.info().append("Prefetch abort at %08x; last good was at %08x", executor_.pc(), last_pc);
executor_.prefetch_abort();
@ -1071,13 +1076,17 @@ class ConcreteMachine:
}
// TODO: pipeline prefetch?
static bool log = false;
// if(executor_.pc() == 0x03803194 || !instruction || instruction == 0xe49aa000) {
// printf("At %08x; after last PC %08x and %zu ago was %08x\n", executor_.pc(), pc_history[(pc_history_ptr - 2 + pc_history.size()) % pc_history.size()], pc_history.size(), pc_history[pc_history_ptr]);
// }
// log |= executor_.registers()[12] == 0xe59ff114;
// log |= (executor_.pc() > 0x02000000 && executor_.pc() < 0x02000078);
log |= executor_.pc() == 0x0207b3bc; //0x397af9c
// log |= executor_.pc() == 0x0380ff4c; //0x397af9c
// log = executor_.pc() == 0x0381202c;
// log |= (executor_.pc() > 0x03801000);
// log &= executor_.pc() != 0x03801a0c;
// log |= instr_count == 71259670 - 50;
// if(executor_.pc() == 0x02000078) {
// if(!all.empty()) {
@ -1093,8 +1102,15 @@ class ConcreteMachine:
// }
if(log) {
InstructionSet::ARM::Disassembler<arm_model> disassembler;
InstructionSet::ARM::dispatch<arm_model>(instruction, disassembler);
auto info = logger.info();
info.append("%08x: %08x prior:[", executor_.pc(), instruction);
info.append("[%d] %08x: %08x\t\t%s\t prior:[",
instr_count,
executor_.pc(),
instruction,
disassembler.last().to_string(executor_.pc()).c_str());
for(uint32_t c = 0; c < 15; c++) {
info.append("r%d:%08x ", c, executor_.registers()[c]);
}
@ -1102,6 +1118,7 @@ class ConcreteMachine:
}
// logger.info().append("%08x: %08x", executor_.pc(), instruction);
InstructionSet::ARM::execute(instruction, executor_);
++instr_count;
// if(
// executor_.pc() > 0x038021d0 &&
@ -1132,6 +1149,10 @@ class ConcreteMachine:
// }
}
if(log) {
printf("");
}
if(!timer_divider_) {
timer_divider_ = TimerTarget;

View File

@ -1807,6 +1807,7 @@
4BA91E1C216D85BA00F79557 /* MasterSystemVDPTests.mm */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.objcpp; path = MasterSystemVDPTests.mm; sourceTree = "<group>"; };
4BA9C3CF1D8164A9002DDB61 /* MediaTarget.hpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.h; path = MediaTarget.hpp; sourceTree = "<group>"; };
4BAA167B21582B1D008A3276 /* Target.hpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.h; path = Target.hpp; sourceTree = "<group>"; };
4BAB1E522BA9D9950002C9B9 /* Disassembler.hpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.h; path = Disassembler.hpp; sourceTree = "<group>"; };
4BAB62AC1D3272D200DF5BA0 /* Disk.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = Disk.hpp; sourceTree = "<group>"; };
4BAB62AE1D32730D00DF5BA0 /* Storage.hpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.h; path = Storage.hpp; sourceTree = "<group>"; };
4BAF2B4C2004580C00480230 /* DMK.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = DMK.cpp; sourceTree = "<group>"; };
@ -2776,6 +2777,7 @@
4B2005482B92697500420C5C /* Executor.hpp */,
4B2005402B804AA300420C5C /* OperationMapper.hpp */,
4B2005462B8BD7A500420C5C /* Registers.hpp */,
4BAB1E522BA9D9950002C9B9 /* Disassembler.hpp */,
);
path = ARM;
sourceTree = "<group>";

View File

@ -425,9 +425,9 @@ struct MemoryLedger {
continue;
}
// if(instruction == 0xe1a0f001 && test_count == 1) {
// printf("");
// }
if(instruction == 0xe79ea10a && test_count == 1) {
printf("");
}
execute(instruction, *test);
NSMutableString *error = nil;