breakpoints
This commit is contained in:
parent
541d0c7829
commit
601c21d802
15 changed files with 480 additions and 26 deletions
|
@ -16,6 +16,11 @@ if (NOT WIN32)
|
||||||
|
|
||||||
add_executable(
|
add_executable(
|
||||||
kek
|
kek
|
||||||
|
breakpoint.cpp
|
||||||
|
breakpoint_and.cpp
|
||||||
|
breakpoint_or.cpp
|
||||||
|
breakpoint_parser.cpp
|
||||||
|
breakpoint_register.cpp
|
||||||
bus.cpp
|
bus.cpp
|
||||||
console.cpp
|
console.cpp
|
||||||
console_ncurses.cpp
|
console_ncurses.cpp
|
||||||
|
|
10
breakpoint.cpp
Normal file
10
breakpoint.cpp
Normal file
|
@ -0,0 +1,10 @@
|
||||||
|
#include "breakpoint.h"
|
||||||
|
|
||||||
|
|
||||||
|
breakpoint::breakpoint(bus *const b) : b(b)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
breakpoint::~breakpoint()
|
||||||
|
{
|
||||||
|
}
|
21
breakpoint.h
Normal file
21
breakpoint.h
Normal file
|
@ -0,0 +1,21 @@
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <optional>
|
||||||
|
#include <string>
|
||||||
|
|
||||||
|
#include "bus.h"
|
||||||
|
|
||||||
|
|
||||||
|
class breakpoint
|
||||||
|
{
|
||||||
|
protected:
|
||||||
|
bus *const b { nullptr };
|
||||||
|
|
||||||
|
public:
|
||||||
|
breakpoint(bus *const b);
|
||||||
|
virtual ~breakpoint();
|
||||||
|
|
||||||
|
virtual std::optional<std::string> is_triggered() const = 0;
|
||||||
|
|
||||||
|
virtual std::string emit() const = 0;
|
||||||
|
};
|
48
breakpoint_and.cpp
Normal file
48
breakpoint_and.cpp
Normal file
|
@ -0,0 +1,48 @@
|
||||||
|
#include "breakpoint_and.h"
|
||||||
|
#include "utils.h"
|
||||||
|
|
||||||
|
|
||||||
|
breakpoint_and::breakpoint_and(bus *const b, const std::vector<breakpoint *> & triggers):
|
||||||
|
breakpoint(b),
|
||||||
|
triggers(triggers)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
breakpoint_and::~breakpoint_and()
|
||||||
|
{
|
||||||
|
for(auto & bp: triggers)
|
||||||
|
delete bp;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::optional<std::string> breakpoint_and::is_triggered() const
|
||||||
|
{
|
||||||
|
std::string out;
|
||||||
|
|
||||||
|
for(auto & t: triggers) {
|
||||||
|
auto rc = t->is_triggered();
|
||||||
|
if (rc.has_value() == false)
|
||||||
|
return { };
|
||||||
|
|
||||||
|
out += (out.empty() ? "" : ", ") + rc.value();
|
||||||
|
}
|
||||||
|
|
||||||
|
return out;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string breakpoint_and::emit() const
|
||||||
|
{
|
||||||
|
std::string out;
|
||||||
|
|
||||||
|
for(auto & t: triggers) {
|
||||||
|
if (out.empty())
|
||||||
|
out = "(";
|
||||||
|
else
|
||||||
|
out += " and ";
|
||||||
|
|
||||||
|
out += t->emit();
|
||||||
|
}
|
||||||
|
|
||||||
|
out += ")";
|
||||||
|
|
||||||
|
return out;
|
||||||
|
}
|
20
breakpoint_and.h
Normal file
20
breakpoint_and.h
Normal file
|
@ -0,0 +1,20 @@
|
||||||
|
#include <optional>
|
||||||
|
#include <string>
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
|
#include "breakpoint.h"
|
||||||
|
|
||||||
|
|
||||||
|
class breakpoint_and : public breakpoint
|
||||||
|
{
|
||||||
|
private:
|
||||||
|
const std::vector<breakpoint *> triggers;
|
||||||
|
|
||||||
|
public:
|
||||||
|
breakpoint_and(bus *const b, const std::vector<breakpoint *> & triggers);
|
||||||
|
virtual ~breakpoint_and();
|
||||||
|
|
||||||
|
virtual std::optional<std::string> is_triggered() const override;
|
||||||
|
|
||||||
|
virtual std::string emit() const override;
|
||||||
|
};
|
44
breakpoint_or.cpp
Normal file
44
breakpoint_or.cpp
Normal file
|
@ -0,0 +1,44 @@
|
||||||
|
#include "breakpoint_or.h"
|
||||||
|
#include "utils.h"
|
||||||
|
|
||||||
|
|
||||||
|
breakpoint_or::breakpoint_or(bus *const b, const std::vector<breakpoint *> & triggers):
|
||||||
|
breakpoint(b),
|
||||||
|
triggers(triggers)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
breakpoint_or::~breakpoint_or()
|
||||||
|
{
|
||||||
|
for(auto & bp: triggers)
|
||||||
|
delete bp;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::optional<std::string> breakpoint_or::is_triggered() const
|
||||||
|
{
|
||||||
|
for(auto & t: triggers) {
|
||||||
|
auto rc = t->is_triggered();
|
||||||
|
if (rc.has_value())
|
||||||
|
return rc;
|
||||||
|
}
|
||||||
|
|
||||||
|
return { };
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string breakpoint_or::emit() const
|
||||||
|
{
|
||||||
|
std::string out;
|
||||||
|
|
||||||
|
for(auto & t: triggers) {
|
||||||
|
if (out.empty())
|
||||||
|
out = "(";
|
||||||
|
else
|
||||||
|
out += " or ";
|
||||||
|
|
||||||
|
out += t->emit();
|
||||||
|
}
|
||||||
|
|
||||||
|
out += ")";
|
||||||
|
|
||||||
|
return out;
|
||||||
|
}
|
20
breakpoint_or.h
Normal file
20
breakpoint_or.h
Normal file
|
@ -0,0 +1,20 @@
|
||||||
|
#include <optional>
|
||||||
|
#include <string>
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
|
#include "breakpoint.h"
|
||||||
|
|
||||||
|
|
||||||
|
class breakpoint_or : public breakpoint
|
||||||
|
{
|
||||||
|
private:
|
||||||
|
const std::vector<breakpoint *> triggers;
|
||||||
|
|
||||||
|
public:
|
||||||
|
breakpoint_or(bus *const b, const std::vector<breakpoint *> & triggers);
|
||||||
|
virtual ~breakpoint_or();
|
||||||
|
|
||||||
|
virtual std::optional<std::string> is_triggered() const override;
|
||||||
|
|
||||||
|
virtual std::string emit() const override;
|
||||||
|
};
|
107
breakpoint_parser.cpp
Normal file
107
breakpoint_parser.cpp
Normal file
|
@ -0,0 +1,107 @@
|
||||||
|
#include <optional>
|
||||||
|
#include <string>
|
||||||
|
|
||||||
|
#include "breakpoint.h"
|
||||||
|
#include "breakpoint_and.h"
|
||||||
|
#include "breakpoint_or.h"
|
||||||
|
#include "breakpoint_register.h"
|
||||||
|
#include "bus.h"
|
||||||
|
#include "utils.h"
|
||||||
|
|
||||||
|
|
||||||
|
static void delete_parsed(const std::vector<breakpoint *> & parsed)
|
||||||
|
{
|
||||||
|
for(auto & p: parsed)
|
||||||
|
delete p;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::pair<breakpoint *, std::optional<std::string> > parse_breakpoint(bus *const b, const std::string & in)
|
||||||
|
{
|
||||||
|
auto parts = split(in, " ");
|
||||||
|
|
||||||
|
std::vector<breakpoint *> parsed;
|
||||||
|
|
||||||
|
enum { combine_not_set, combine_single, combine_and, combine_or } combine { combine_not_set };
|
||||||
|
|
||||||
|
for(size_t i=0; i<parts.size(); i++) {
|
||||||
|
std::pair<breakpoint *, std::optional<std::string> > current;
|
||||||
|
|
||||||
|
if (parts[i][0] == '(') {
|
||||||
|
int depth = 0;
|
||||||
|
|
||||||
|
std::optional<size_t> end_index;
|
||||||
|
for(size_t j=i; j<parts.size(); j++) {
|
||||||
|
if (parts[j][0] == '(')
|
||||||
|
depth++;
|
||||||
|
|
||||||
|
for(size_t count=0; count<parts[j].size(); count++) {
|
||||||
|
if (parts[j][count] == ')')
|
||||||
|
depth--;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (depth == 0) {
|
||||||
|
end_index = j;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (depth != 0) {
|
||||||
|
delete_parsed(parsed);
|
||||||
|
return { nullptr, "( and ) unbalanced: " + in };
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string temp;
|
||||||
|
for(size_t j=i; j<=end_index.value(); j++)
|
||||||
|
temp += (j > i ? " " : "") + parts.at(j);
|
||||||
|
|
||||||
|
auto rc = parse_breakpoint(b, temp.substr(1, temp.size() - 2));
|
||||||
|
if (rc.first == nullptr) {
|
||||||
|
delete_parsed(parsed);
|
||||||
|
return rc;
|
||||||
|
}
|
||||||
|
|
||||||
|
i = end_index.value();
|
||||||
|
|
||||||
|
parsed.push_back(rc.first);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
if (parts[i] == "and" || parts[i] == "or") {
|
||||||
|
if ((combine == combine_and && parts[i] == "or") || (combine == combine_or && parts[i] == "and")) {
|
||||||
|
delete_parsed(parsed);
|
||||||
|
return { nullptr, "combining and/or in one definition" };
|
||||||
|
}
|
||||||
|
combine = parts[i] == "and" ? combine_and : combine_or;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
else if (combine == combine_single) {
|
||||||
|
delete_parsed(parsed);
|
||||||
|
return { nullptr, "and/or missing" };
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
if (combine == combine_not_set)
|
||||||
|
combine = combine_single;
|
||||||
|
|
||||||
|
auto rc_reg = breakpoint_register::parse(b, parts[i]);
|
||||||
|
if (rc_reg.first == nullptr) {
|
||||||
|
delete_parsed(parsed);
|
||||||
|
return { nullptr, "not understood" };
|
||||||
|
}
|
||||||
|
|
||||||
|
parsed.push_back(rc_reg.first);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (combine == combine_and)
|
||||||
|
return { new breakpoint_and(b, parsed), { } };
|
||||||
|
|
||||||
|
if (combine == combine_or)
|
||||||
|
return { new breakpoint_or(b, parsed), { } };
|
||||||
|
|
||||||
|
if (parsed.size() != 1) {
|
||||||
|
delete_parsed(parsed);
|
||||||
|
return { nullptr, "wrong count of items" };
|
||||||
|
}
|
||||||
|
|
||||||
|
return { parsed.at(0), { } };
|
||||||
|
}
|
8
breakpoint_parser.h
Normal file
8
breakpoint_parser.h
Normal file
|
@ -0,0 +1,8 @@
|
||||||
|
#include <optional>
|
||||||
|
#include <string>
|
||||||
|
|
||||||
|
#include "breakpoint.h"
|
||||||
|
#include "bus.h"
|
||||||
|
|
||||||
|
|
||||||
|
std::pair<breakpoint *, std::optional<std::string> > parse_breakpoint(bus *const b, const std::string & in);
|
77
breakpoint_register.cpp
Normal file
77
breakpoint_register.cpp
Normal file
|
@ -0,0 +1,77 @@
|
||||||
|
#include <ctype.h>
|
||||||
|
|
||||||
|
#include "breakpoint_register.h"
|
||||||
|
#include "cpu.h"
|
||||||
|
#include "utils.h"
|
||||||
|
|
||||||
|
|
||||||
|
breakpoint_register::breakpoint_register(bus *const b, const int register_nr, const std::set<uint16_t> & values) :
|
||||||
|
breakpoint(b),
|
||||||
|
c(b->getCpu()),
|
||||||
|
register_nr(register_nr), values(values)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
breakpoint_register::~breakpoint_register()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
std::optional<std::string> breakpoint_register::is_triggered() const
|
||||||
|
{
|
||||||
|
uint16_t v = c->getRegister(register_nr); // TODO run-mode
|
||||||
|
|
||||||
|
auto it = values.find(v);
|
||||||
|
if (it == values.end())
|
||||||
|
return { };
|
||||||
|
|
||||||
|
return format("R%d=%06o", register_nr, v);
|
||||||
|
}
|
||||||
|
|
||||||
|
std::pair<breakpoint_register *, std::optional<std::string> > breakpoint_register::parse(bus *const b, const std::string & in)
|
||||||
|
{
|
||||||
|
auto parts = split(in, "=");
|
||||||
|
if (parts.size() != 2)
|
||||||
|
return { nullptr, "register: 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() < 2)
|
||||||
|
return { nullptr, "register: register id invalid" };
|
||||||
|
|
||||||
|
if (toupper(key[0]) == 'R') {
|
||||||
|
int nr = key[1] - '0';
|
||||||
|
if (nr < 0 || nr > 7)
|
||||||
|
return { nullptr, "register: register id invalid" };
|
||||||
|
|
||||||
|
return { new breakpoint_register(b, nr, values), { } };
|
||||||
|
}
|
||||||
|
else if (key == "SP" || key == "sp") {
|
||||||
|
return { new breakpoint_register(b, 6, values), { } };
|
||||||
|
}
|
||||||
|
else if (key == "PC" || key == "pc") {
|
||||||
|
return { new breakpoint_register(b, 7, values), { } };
|
||||||
|
}
|
||||||
|
|
||||||
|
return { nullptr, "register: invalid specification" };
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string breakpoint_register::emit() const
|
||||||
|
{
|
||||||
|
std::string out;
|
||||||
|
|
||||||
|
for(auto & v: values) {
|
||||||
|
if (out.empty())
|
||||||
|
out = format("R%d", register_nr) + "=";
|
||||||
|
else
|
||||||
|
out += ",";
|
||||||
|
|
||||||
|
out += format("%06o", v);
|
||||||
|
}
|
||||||
|
|
||||||
|
return out;
|
||||||
|
}
|
25
breakpoint_register.h
Normal file
25
breakpoint_register.h
Normal file
|
@ -0,0 +1,25 @@
|
||||||
|
#include <optional>
|
||||||
|
#include <set>
|
||||||
|
#include <string>
|
||||||
|
|
||||||
|
#include "breakpoint.h"
|
||||||
|
#include "bus.h"
|
||||||
|
|
||||||
|
|
||||||
|
class breakpoint_register : public breakpoint
|
||||||
|
{
|
||||||
|
private:
|
||||||
|
cpu *const c { nullptr };
|
||||||
|
int register_nr { -1 };
|
||||||
|
std::set<uint16_t> values;
|
||||||
|
|
||||||
|
public:
|
||||||
|
breakpoint_register(bus *const b, const int register_nr, const std::set<uint16_t> & values);
|
||||||
|
virtual ~breakpoint_register();
|
||||||
|
|
||||||
|
virtual std::optional<std::string> is_triggered() const override;
|
||||||
|
|
||||||
|
static std::pair<breakpoint_register *, std::optional<std::string> > parse(bus *const b, const std::string & in);
|
||||||
|
|
||||||
|
virtual std::string emit() const override;
|
||||||
|
};
|
34
cpu.cpp
34
cpu.cpp
|
@ -44,22 +44,42 @@ void cpu::emulation_start()
|
||||||
wait_time = 0;
|
wait_time = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool cpu::check_breakpoint()
|
std::optional<std::string> cpu::check_breakpoint()
|
||||||
{
|
{
|
||||||
return breakpoints.find(getPC()) != breakpoints.end();
|
for(auto & bp: breakpoints) {
|
||||||
|
auto rc = bp.second->is_triggered();
|
||||||
|
if (rc.has_value())
|
||||||
|
return rc;
|
||||||
|
}
|
||||||
|
|
||||||
|
return { };
|
||||||
}
|
}
|
||||||
|
|
||||||
void cpu::set_breakpoint(const uint16_t addr)
|
int cpu::set_breakpoint(breakpoint *const bp)
|
||||||
{
|
{
|
||||||
breakpoints.insert(addr);
|
int id = 0;
|
||||||
|
|
||||||
|
do {
|
||||||
|
id = rand();
|
||||||
|
} while(breakpoints.find(id) != breakpoints.end());
|
||||||
|
|
||||||
|
breakpoints.insert({ id, bp });
|
||||||
|
|
||||||
|
return id;
|
||||||
}
|
}
|
||||||
|
|
||||||
void cpu::remove_breakpoint(const uint16_t addr)
|
bool cpu::remove_breakpoint(const int bp_id)
|
||||||
{
|
{
|
||||||
breakpoints.erase(addr);
|
auto it = breakpoints.find(bp_id);
|
||||||
|
if (it == breakpoints.end())
|
||||||
|
return false;
|
||||||
|
|
||||||
|
delete it->second;
|
||||||
|
|
||||||
|
return breakpoints.erase(bp_id) == 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::set<uint16_t> cpu::list_breakpoints()
|
std::map<int, breakpoint *> cpu::list_breakpoints()
|
||||||
{
|
{
|
||||||
return breakpoints;
|
return breakpoints;
|
||||||
}
|
}
|
||||||
|
|
11
cpu.h
11
cpu.h
|
@ -12,6 +12,7 @@
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
|
#include "breakpoint.h"
|
||||||
#include "bus.h"
|
#include "bus.h"
|
||||||
|
|
||||||
|
|
||||||
|
@ -62,7 +63,7 @@ private:
|
||||||
#endif
|
#endif
|
||||||
std::atomic_bool any_queued_interrupts { false };
|
std::atomic_bool any_queued_interrupts { false };
|
||||||
|
|
||||||
std::set<uint16_t> breakpoints;
|
std::map<int, breakpoint *> breakpoints;
|
||||||
|
|
||||||
bus *const b { nullptr };
|
bus *const b { nullptr };
|
||||||
|
|
||||||
|
@ -98,10 +99,10 @@ public:
|
||||||
explicit cpu(bus *const b, std::atomic_uint32_t *const event);
|
explicit cpu(bus *const b, std::atomic_uint32_t *const event);
|
||||||
~cpu();
|
~cpu();
|
||||||
|
|
||||||
bool check_breakpoint();
|
std::optional<std::string> check_breakpoint();
|
||||||
void set_breakpoint(const uint16_t addr);
|
int set_breakpoint(breakpoint *const bp);
|
||||||
void remove_breakpoint(const uint16_t addr);
|
bool remove_breakpoint(const int bp_id);
|
||||||
std::set<uint16_t> list_breakpoints();
|
std::map<int, breakpoint *> list_breakpoints();
|
||||||
|
|
||||||
void disassemble(void) const;
|
void disassemble(void) const;
|
||||||
std::map<std::string, std::vector<std::string> > disassemble(const uint16_t addr) const;
|
std::map<std::string, std::vector<std::string> > disassemble(const uint16_t addr) const;
|
||||||
|
|
55
debugger.cpp
55
debugger.cpp
|
@ -13,6 +13,7 @@
|
||||||
#include <LittleFS.h>
|
#include <LittleFS.h>
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#include "breakpoint_parser.h"
|
||||||
#include "bus.h"
|
#include "bus.h"
|
||||||
#include "console.h"
|
#include "console.h"
|
||||||
#include "cpu.h"
|
#include "cpu.h"
|
||||||
|
@ -531,6 +532,22 @@ int disassemble(cpu *const c, console *const cnsl, const uint16_t pc, const bool
|
||||||
|
|
||||||
DOLOG(debug, false, "SP: %s", sp.c_str());
|
DOLOG(debug, false, "SP: %s", sp.c_str());
|
||||||
|
|
||||||
|
#if 0
|
||||||
|
if (c->getPSW_runmode() == 3) {
|
||||||
|
/*
|
||||||
|
FILE *fh = fopen("/home/folkert/temp/ramdisk/log-kek.dat", "a+");
|
||||||
|
fprintf(fh, "%06o", pc);
|
||||||
|
for(auto & v: data["instruction-values"])
|
||||||
|
fprintf(fh, " %s", v.c_str());
|
||||||
|
fprintf(fh, "\n");
|
||||||
|
fclose(fh);
|
||||||
|
*/
|
||||||
|
FILE *fh = fopen("/home/folkert/temp/ramdisk/da-kek.txt", "a+");
|
||||||
|
fprintf(fh, "R0 %s R1 %s R2 %s R3 %s R4 %s R5 %s R6 %s R7 %06o %s\n", registers[0].c_str(), registers[1].c_str(), registers[2].c_str(), registers[3].c_str(), registers[4].c_str(), registers[5].c_str(), registers[6].c_str(), pc, instruction.c_str());
|
||||||
|
fclose(fh);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
return data["instruction-values"].size() * 2;
|
return data["instruction-values"].size() * 2;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -737,18 +754,29 @@ void debugger(console *const cnsl, bus *const b, std::atomic_uint32_t *const sto
|
||||||
|
|
||||||
*stop_event = EVENT_NONE;
|
*stop_event = EVENT_NONE;
|
||||||
}
|
}
|
||||||
else if ((parts[0] == "sbp" || parts[0] == "cbp") && parts.size() == 2){
|
else if ((parts[0] == "sbp" || parts[0] == "cbp") && parts.size() >= 2){
|
||||||
uint16_t pc = std::stoi(parts[1].c_str(), nullptr, 8);
|
|
||||||
|
|
||||||
if (parts[0] == "sbp") {
|
if (parts[0] == "sbp") {
|
||||||
c->set_breakpoint(pc);
|
std::size_t space = cmd.find(" ");
|
||||||
|
|
||||||
cnsl->put_string_lf(format("Set breakpoint at %06o", pc));
|
std::pair<breakpoint *, std::optional<std::string> > rc = parse_breakpoint(b, cmd.substr(space + 1));
|
||||||
|
|
||||||
|
if (rc.first == nullptr) {
|
||||||
|
if (rc.second.has_value())
|
||||||
|
cnsl->put_string_lf(rc.second.value());
|
||||||
|
else
|
||||||
|
cnsl->put_string_lf("not set");
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
c->remove_breakpoint(pc);
|
int id = c->set_breakpoint(rc.first);
|
||||||
|
|
||||||
cnsl->put_string_lf(format("Clear breakpoint at %06o", pc));
|
cnsl->put_string_lf(format("Breakpoint has id: %d", id));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
if (c->remove_breakpoint(std::stoi(parts[1])))
|
||||||
|
cnsl->put_string_lf("Breakpoint cleared");
|
||||||
|
else
|
||||||
|
cnsl->put_string_lf("Breakpoint not found");
|
||||||
}
|
}
|
||||||
|
|
||||||
continue;
|
continue;
|
||||||
|
@ -758,11 +786,11 @@ void debugger(console *const cnsl, bus *const b, std::atomic_uint32_t *const sto
|
||||||
|
|
||||||
cnsl->put_string_lf("Breakpoints:");
|
cnsl->put_string_lf("Breakpoints:");
|
||||||
|
|
||||||
for(auto a : bps) {
|
for(auto a : bps)
|
||||||
cnsl->put_string(format(" %06o> ", a));
|
cnsl->put_string_lf(format("%d: %s", a.first, a.second->emit().c_str()));
|
||||||
|
|
||||||
disassemble(c, cnsl, a, true);
|
if (bps.empty())
|
||||||
}
|
cnsl->put_string_lf("(none)");
|
||||||
|
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
@ -1046,8 +1074,9 @@ void debugger(console *const cnsl, bus *const b, std::atomic_uint32_t *const sto
|
||||||
if ((tracing || single_step) && (t_rl.has_value() == false || t_rl.value() == c->getPSW_runmode()))
|
if ((tracing || single_step) && (t_rl.has_value() == false || t_rl.value() == c->getPSW_runmode()))
|
||||||
disassemble(c, single_step ? cnsl : nullptr, c->getPC(), false);
|
disassemble(c, single_step ? cnsl : nullptr, c->getPC(), false);
|
||||||
|
|
||||||
if (c->check_breakpoint() && !single_step) {
|
auto bp_result = c->check_breakpoint();
|
||||||
cnsl->put_string_lf("Breakpoint");
|
if (bp_result.has_value() && !single_step) {
|
||||||
|
cnsl->put_string_lf("Breakpoint: " + bp_result.value());
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
19
main.cpp
19
main.cpp
|
@ -314,8 +314,27 @@ void help()
|
||||||
printf("-M log metrics\n");
|
printf("-M log metrics\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#include "breakpoint_parser.h"
|
||||||
int main(int argc, char *argv[])
|
int main(int argc, char *argv[])
|
||||||
{
|
{
|
||||||
|
#if 0
|
||||||
|
{
|
||||||
|
bus *b = new bus();
|
||||||
|
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))");
|
||||||
|
printf("%p\n", rc.first);
|
||||||
|
|
||||||
|
if (rc.second.has_value())
|
||||||
|
printf("%s\n", rc.second.value().c_str());
|
||||||
|
delete rc.first;
|
||||||
|
delete b;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
#endif
|
||||||
|
|
||||||
//setlocale(LC_ALL, "");
|
//setlocale(LC_ALL, "");
|
||||||
|
|
||||||
std::vector<disk_backend *> rk05_files;
|
std::vector<disk_backend *> rk05_files;
|
||||||
|
|
Loading…
Add table
Reference in a new issue