memory breakpoint

This commit is contained in:
folkert van heusden 2024-04-16 14:22:06 +02:00
parent 70cd49e2a9
commit 4e39cc3329
Signed by untrusted user who does not match committer: folkert
GPG key ID: 6B6455EDFEED3BD1
7 changed files with 122 additions and 6 deletions

View file

@ -18,6 +18,7 @@ add_executable(
kek
breakpoint.cpp
breakpoint_and.cpp
breakpoint_memory.cpp
breakpoint_or.cpp
breakpoint_parser.cpp
breakpoint_register.cpp

76
breakpoint_memory.cpp Normal file
View file

@ -0,0 +1,76 @@
#include <ctype.h>
#include "breakpoint_memory.h"
#include "cpu.h"
#include "utils.h"
breakpoint_memory::breakpoint_memory(bus *const b, const uint32_t addr, const word_mode_t word_mode, const bool is_virtual, const std::set<uint16_t> & values):
breakpoint(b),
addr(addr),
word_mode(word_mode),
is_virtual(is_virtual),
values(values)
{
}
breakpoint_memory::~breakpoint_memory()
{
}
std::optional<std::string> breakpoint_memory::is_triggered() const
{
uint16_t v = 0;
if (is_virtual)
v = b->read(addr, word_mode, rm_cur, true, i_space);
else
v = b->readPhysical(addr);
auto it = values.find(v);
if (it == values.end())
return { };
return format("MEM%c%c[%08a]=%06o", word_mode == wm_byte ? 'B' : 'W', is_virtual ? 'V' : 'P', addr, v);
}
std::pair<breakpoint_memory *, std::optional<std::string> > breakpoint_memory::parse(bus *const b, const std::string & in)
{
auto parts = split(in, "=");
if (parts.size() != 2)
return { nullptr, "memory: key or value missing" };
auto values_in = parts.at(1);
auto v_parts = split(values_in, ",");
std::set<uint16_t> values;
for(auto & v: v_parts)
values.insert(std::stoi(v, nullptr, 8));
auto key = parts.at(0);
if (key.size() < 8 || (key.substr(0, 3) != "MEM" && key.substr(0, 3) != "mem"))
return { nullptr, { } };
word_mode_t wm = toupper(key[3]) == 'B' ? wm_byte : wm_word;
bool is_virtual = toupper(key[4]) == 'V';
std::size_t end_marker = key.find(']');
uint32_t addr = std::stoi(key.substr(6, end_marker - 6), nullptr, 8);
return { new breakpoint_memory(b, addr, wm, is_virtual, values), { } };
}
std::string breakpoint_memory::emit() const
{
std::string out;
for(auto & v: values) {
if (out.empty())
out = format("MEM%c%c[%08a]=", word_mode == wm_byte ? 'B' : 'W', is_virtual ? 'V' : 'P', addr);
else
out += ",";
out += format("%06o", v);
}
return out;
}

26
breakpoint_memory.h Normal file
View file

@ -0,0 +1,26 @@
#include <optional>
#include <set>
#include <string>
#include "breakpoint.h"
#include "bus.h"
class breakpoint_memory : public breakpoint
{
private:
const uint32_t addr { 0 };
const word_mode_t word_mode { wm_word };
const bool is_virtual { false };
std::set<uint16_t> values;
public:
breakpoint_memory(bus *const b, const uint32_t addr, const word_mode_t word_mode, const bool is_virtual, const std::set<uint16_t> & values);
virtual ~breakpoint_memory();
virtual std::optional<std::string> is_triggered() const override;
static std::pair<breakpoint_memory *, std::optional<std::string> > parse(bus *const b, const std::string & in);
virtual std::string emit() const override;
};

View file

@ -3,6 +3,7 @@
#include "breakpoint.h"
#include "breakpoint_and.h"
#include "breakpoint_memory.h"
#include "breakpoint_or.h"
#include "breakpoint_register.h"
#include "bus.h"
@ -82,12 +83,22 @@ std::pair<breakpoint *, std::optional<std::string> > parse_breakpoint(bus *const
combine = combine_single;
auto rc_reg = breakpoint_register::parse(b, parts[i]);
if (rc_reg.first == nullptr) {
if (rc_reg.first == nullptr && rc_reg.second.has_value()) {
delete_parsed(parsed);
return { nullptr, "not understood" };
return { nullptr, "not understood: " + rc_reg.second.value() };
}
parsed.push_back(rc_reg.first);
if (rc_reg.first)
parsed.push_back(rc_reg.first);
auto rc_mem = breakpoint_memory::parse(b, parts[i]);
if (rc_mem.first == nullptr && rc_mem.second.has_value()) {
delete_parsed(parsed);
return { nullptr, "not understood: " + rc_mem.second.value() };
}
if (rc_mem.first)
parsed.push_back(rc_mem.first);
}
}
}

View file

@ -57,7 +57,7 @@ std::pair<breakpoint_register *, std::optional<std::string> > breakpoint_registe
return { new breakpoint_register(b, 7, values), { } };
}
return { nullptr, "register: invalid specification" };
return { nullptr, { } };
}
std::string breakpoint_register::emit() const

View file

@ -1024,7 +1024,9 @@ void debugger(console *const cnsl, bus *const b, std::atomic_uint32_t *const sto
cnsl->put_string_lf("reset/r - reset cpu/bus/etc");
cnsl->put_string_lf("single/s - run 1 instruction (implicit 'disassemble' command)");
cnsl->put_string_lf("sbp/cbp/lbp - set/clear/list breakpoint(s)");
cnsl->put_string_lf(" e.g.: (pc=0123 and r0=123 and (r4=07 or r4=0456))");
cnsl->put_string_lf(" e.g.: (pc=0123 and memwv[04000]=0200,0300 and (r4=07,05 or r5=0456))");
cnsl->put_string_lf(" values seperated by ',', char after mem is w/b (word/byte), then
cnsl->put_string_lf(" follows v/p (virtual/physical)");
cnsl->put_string_lf("trace/t - toggle tracing");
cnsl->put_string_lf("turbo - toggle turbo mode (cannot be interrupted)");
cnsl->put_string_lf("strace - start tracing from address - invoke without address to disable");

View file

@ -323,7 +323,7 @@ int main(int argc, char *argv[])
cpu *c = new cpu(b, &event);
b->add_cpu(c);
std::pair<breakpoint *, std::optional<std::string> > rc = parse_breakpoint(b, "(pc=0123 and (r0=01456 or r2=1))");
std::pair<breakpoint *, std::optional<std::string> > rc = parse_breakpoint(b, "(pc=0123 and (r0=01456 or r2=1) and memWV[0444]=0222)");
printf("%p\n", rc.first);
if (rc.second.has_value())