aboutsummaryrefslogtreecommitdiff
path: root/qtmips_machine
diff options
context:
space:
mode:
Diffstat (limited to 'qtmips_machine')
-rw-r--r--qtmips_machine/core.cpp47
-rw-r--r--qtmips_machine/core.h6
-rw-r--r--qtmips_machine/machineconfig.cpp51
-rw-r--r--qtmips_machine/machineconfig.h13
-rw-r--r--qtmips_machine/machinedefs.h1
-rw-r--r--qtmips_machine/qtmipsmachine.cpp33
-rw-r--r--qtmips_machine/qtmipsmachine.h4
7 files changed, 143 insertions, 12 deletions
diff --git a/qtmips_machine/core.cpp b/qtmips_machine/core.cpp
index 2b8c3bc..2d52203 100644
--- a/qtmips_machine/core.cpp
+++ b/qtmips_machine/core.cpp
@@ -52,6 +52,11 @@ Core::Core(Registers *regs, MemoryAccess *mem_program, MemoryAccess *mem_data,
this->hwr_userlocal = 0xe0000000;
if (cop0state != nullptr)
cop0state->setup_core(this);
+ for (int i = 0; i < EXCAUSE_COUNT; i++) {
+ stop_on_exception[i] = true;
+ step_over_exception[i] = true;
+ }
+ step_over_exception[EXCAUSE_INT] = false;
}
void Core::step(bool skip_break) {
@@ -107,6 +112,22 @@ bool Core::is_hwbreak(std::uint32_t address) {
return hwbrk != nullptr;
}
+void Core::set_stop_on_exception(enum ExceptionCause excause, bool value) {
+ stop_on_exception[excause] = value;
+}
+
+bool Core::get_stop_on_exception(enum ExceptionCause excause) const {
+ return stop_on_exception[excause];
+}
+
+void Core::set_step_over_exception(enum ExceptionCause excause, bool value) {
+ step_over_exception[excause] = value;
+}
+
+bool Core::get_step_over_exception(enum ExceptionCause excause) const {
+ return step_over_exception[excause];
+}
+
void Core::register_exception_handler(ExceptionCause excause, ExceptionHandler *exhandler)
{
if (excause == EXCAUSE_NONE ) {
@@ -125,6 +146,7 @@ bool Core::handle_exception(Core *core, Registers *regs, ExceptionCause excause,
std::uint32_t jump_branch_pc, bool in_delay_slot,
std::uint32_t mem_ref_addr)
{
+ bool ret = false;
if (excause == EXCAUSE_HWBREAK) {
if (in_delay_slot)
regs->pc_abs_jmp(jump_branch_pc);
@@ -138,24 +160,26 @@ bool Core::handle_exception(Core *core, Registers *regs, ExceptionCause excause,
else
cop0state->write_cop0reg(Cop0State::EPC, inst_addr);
cop0state->update_execption_cause(excause, in_delay_slot);
- if (cop0state->read_cop0reg(Cop0State::EBase) != 0) {
- if (excause == EXCAUSE_INT) {
- cop0state->set_status_exl(true);
- regs->pc_abs_jmp(cop0state->exception_pc_address());
- }
+ if (cop0state->read_cop0reg(Cop0State::EBase) != 0 &&
+ !get_step_over_exception(excause)) {
+ cop0state->set_status_exl(true);
+ regs->pc_abs_jmp(cop0state->exception_pc_address());
}
}
ExceptionHandler *exhandler = ex_handlers.value(excause);
if (exhandler != nullptr)
- return exhandler->handle_exception(core, regs, excause, inst_addr,
+ ret = exhandler->handle_exception(core, regs, excause, inst_addr,
next_addr, jump_branch_pc, in_delay_slot,
mem_ref_addr);
- if (ex_default_handler != nullptr)
- return ex_default_handler->handle_exception(core, regs, excause, inst_addr,
- next_addr, jump_branch_pc, in_delay_slot,
- mem_ref_addr);
- return false;
+ else if (ex_default_handler != nullptr)
+ ret = ex_default_handler->handle_exception(core, regs, excause, inst_addr,
+ next_addr, jump_branch_pc, in_delay_slot,
+ mem_ref_addr);
+ if (get_stop_on_exception(excause))
+ emit core->stop_on_exception_reached();
+
+ return ret;
}
void Core::set_c0_userlocal(std::uint32_t address) {
@@ -883,6 +907,5 @@ bool StopExceptionHandler::handle_exception(Core *core, Registers *regs,
(void)excause; (void)inst_addr; (void)next_addr; (void)mem_ref_addr; (void)regs;
(void)jump_branch_pc; (void)in_delay_slot;
#endif
- emit core->stop_on_exception_reached();
return true;
};
diff --git a/qtmips_machine/core.h b/qtmips_machine/core.h
index d5ac4e2..52cadb4 100644
--- a/qtmips_machine/core.h
+++ b/qtmips_machine/core.h
@@ -86,6 +86,10 @@ public:
void insert_hwbreak(std::uint32_t address);
void remove_hwbreak(std::uint32_t address);
bool is_hwbreak(std::uint32_t address);
+ void set_stop_on_exception(enum ExceptionCause excause, bool value);
+ bool get_stop_on_exception(enum ExceptionCause excause) const;
+ void set_step_over_exception(enum ExceptionCause excause, bool value);
+ bool get_step_over_exception(enum ExceptionCause excause) const;
void set_c0_userlocal(std::uint32_t address);
@@ -275,6 +279,8 @@ private:
unsigned int min_cache_row_size;
std::uint32_t hwr_userlocal;
QMap<std::uint32_t, hwBreak *> hw_breaks;
+ bool stop_on_exception[EXCAUSE_COUNT];
+ bool step_over_exception[EXCAUSE_COUNT];
};
class CoreSingle : public Core {
diff --git a/qtmips_machine/machineconfig.cpp b/qtmips_machine/machineconfig.cpp
index 4d9728d..36b376f 100644
--- a/qtmips_machine/machineconfig.cpp
+++ b/qtmips_machine/machineconfig.cpp
@@ -201,6 +201,11 @@ MachineConfig::MachineConfig(const MachineConfig *cc) {
mem_acc_read = cc->memory_access_time_read();
mem_acc_write = cc->memory_access_time_write();
mem_acc_burst = cc->memory_access_time_burst();
+ osem_enable = cc->osemu_enable();
+ osem_known_syscall_stop = cc->osemu_known_syscall_stop();
+ osem_unknown_syscall_stop = cc->osemu_unknown_syscall_stop();
+ osem_interrupt_stop = cc->osemu_interrupt_stop();
+ osem_exception_stop = cc->osemu_exception_stop();
elf_path = cc->elf();
cch_program = cc->cache_program();
cch_data = cc->cache_data();
@@ -217,6 +222,11 @@ MachineConfig::MachineConfig(const QSettings *sts, const QString &prefix) {
mem_acc_read = sts->value(N("MemoryRead"), DF_MEM_ACC_READ).toUInt();
mem_acc_write = sts->value(N("MemoryWrite"), DF_MEM_ACC_WRITE).toUInt();
mem_acc_burst = sts->value(N("MemoryBurts"), DF_MEM_ACC_BURST).toUInt();
+ osem_enable = sts->value(N("OsemuEnable"), true).toBool();
+ osem_known_syscall_stop = sts->value(N("OsemuKnownSyscallStop"), true).toBool();
+ osem_unknown_syscall_stop = sts->value(N("OsemuUnknownSyscallStop"), true).toBool();
+ osem_interrupt_stop = sts->value(N("OsemuInterruptStop"), true).toBool();
+ osem_exception_stop = sts->value(N("OsemuExceptionStop"), true).toBool();
elf_path = sts->value(N("Elf"), DF_ELF).toString();
cch_program = MachineConfigCache(sts, N("ProgramCache_"));
cch_data = MachineConfigCache(sts, N("DataCache_"));
@@ -229,6 +239,11 @@ void MachineConfig::store(QSettings *sts, const QString &prefix) {
sts->setValue(N("MemoryRead"), memory_access_time_read());
sts->setValue(N("MemoryWrite"), memory_access_time_write());
sts->setValue(N("MemoryBurts"), memory_access_time_burst());
+ sts->setValue(N("OsemuEnable"), osemu_enable());
+ sts->setValue(N("OsemuKnownSyscallStop"), osemu_known_syscall_stop());
+ sts->setValue(N("OsemuUnknownSyscallStop"), osemu_unknown_syscall_stop());
+ sts->setValue(N("OsemuInterruptStop"), osemu_interrupt_stop());
+ sts->setValue(N("OsemuExceptionStop"), osemu_exception_stop());
sts->setValue(N("Elf"), elf_path);
cch_program.store(sts, N("ProgramCache_"));
cch_data.store(sts, N("DataCache_"));
@@ -296,6 +311,26 @@ void MachineConfig::set_memory_access_time_burst(unsigned v) {
mem_acc_burst = v;
}
+void MachineConfig::set_osemu_enable(bool v) {
+ osem_enable = v;
+}
+
+void MachineConfig::set_osemu_known_syscall_stop(bool v) {
+ osem_known_syscall_stop = v;
+}
+
+void MachineConfig::set_osemu_unknown_syscall_stop(bool v) {
+ osem_unknown_syscall_stop = v;
+}
+
+void MachineConfig::set_osemu_interrupt_stop(bool v) {
+ osem_interrupt_stop = v;
+}
+
+void MachineConfig::set_osemu_exception_stop(bool v) {
+ osem_exception_stop = v;
+}
+
void MachineConfig::set_elf(QString path) {
elf_path = path;
}
@@ -342,6 +377,22 @@ unsigned MachineConfig::memory_access_time_burst() const {
return mem_acc_burst;
}
+bool MachineConfig::osemu_enable() const {
+ return osem_enable;
+}
+bool MachineConfig::osemu_known_syscall_stop() const {
+ return osem_known_syscall_stop;
+}
+bool MachineConfig::osemu_unknown_syscall_stop() const {
+ return osem_unknown_syscall_stop;
+}
+bool MachineConfig::osemu_interrupt_stop() const {
+ return osem_interrupt_stop;
+}
+bool MachineConfig::osemu_exception_stop() const {
+ return osem_exception_stop;
+}
+
QString MachineConfig::elf() const {
return elf_path;
}
diff --git a/qtmips_machine/machineconfig.h b/qtmips_machine/machineconfig.h
index 6f53d87..9fbbf18 100644
--- a/qtmips_machine/machineconfig.h
+++ b/qtmips_machine/machineconfig.h
@@ -127,6 +127,12 @@ public:
void set_memory_access_time_read(unsigned);
void set_memory_access_time_write(unsigned);
void set_memory_access_time_burst(unsigned);
+ // Operating system and exceptions setup
+ void set_osemu_enable(bool);
+ void set_osemu_known_syscall_stop(bool);
+ void set_osemu_unknown_syscall_stop(bool);
+ void set_osemu_interrupt_stop(bool);
+ void set_osemu_exception_stop(bool);
// Set path to source elf file. This has to be set before core is initialized.
void set_elf(QString path);
// Configure cache
@@ -141,6 +147,11 @@ public:
unsigned memory_access_time_read() const;
unsigned memory_access_time_write() const;
unsigned memory_access_time_burst() const;
+ bool osemu_enable() const;
+ bool osemu_known_syscall_stop() const;
+ bool osemu_unknown_syscall_stop() const;
+ bool osemu_interrupt_stop() const;
+ bool osemu_exception_stop() const;
QString elf() const;
const MachineConfigCache &cache_program() const;
const MachineConfigCache &cache_data() const;
@@ -156,6 +167,8 @@ private:
enum HazardUnit hunit;
bool exec_protect, write_protect;
unsigned mem_acc_read, mem_acc_write, mem_acc_burst;
+ bool osem_enable, osem_known_syscall_stop, osem_unknown_syscall_stop;
+ bool osem_interrupt_stop, osem_exception_stop;
QString elf_path;
MachineConfigCache cch_program, cch_data;
};
diff --git a/qtmips_machine/machinedefs.h b/qtmips_machine/machinedefs.h
index 8ccc81c..d8219b6 100644
--- a/qtmips_machine/machinedefs.h
+++ b/qtmips_machine/machinedefs.h
@@ -69,6 +69,7 @@ enum ExceptionCause {
EXCAUSE_OVERFLOW = 12,
EXCAUSE_TRAP = 13,
EXCAUSE_HWBREAK = 14,
+ EXCAUSE_COUNT = 15,
};
enum AluOp : std::uint8_t {
diff --git a/qtmips_machine/qtmipsmachine.cpp b/qtmips_machine/qtmipsmachine.cpp
index afcae54..c8b072b 100644
--- a/qtmips_machine/qtmipsmachine.cpp
+++ b/qtmips_machine/qtmipsmachine.cpp
@@ -95,6 +95,17 @@ QtMipsMachine::QtMipsMachine(const MachineConfig &cc, bool load_symtab) :
run_t = new QTimer(this);
set_speed(0); // In default run as fast as possible
connect(run_t, SIGNAL(timeout()), this, SLOT(step_timer()));
+
+ for (int i = 0; i < EXCAUSE_COUNT; i++) {
+ if (i != EXCAUSE_INT && i != EXCAUSE_BREAK && i != EXCAUSE_HWBREAK) {
+
+ }
+ set_stop_on_exception((enum ExceptionCause)i, cc.osemu_exception_stop());
+ set_step_over_exception((enum ExceptionCause)i, cc.osemu_exception_stop());
+ }
+
+ set_stop_on_exception(EXCAUSE_INT, cc.osemu_interrupt_stop());
+ set_step_over_exception(EXCAUSE_INT, false);
}
QtMipsMachine::~QtMipsMachine() {
@@ -300,3 +311,25 @@ bool QtMipsMachine::is_hwbreak(std::uint32_t address) {
return cr->is_hwbreak(address);
return false;
}
+
+void QtMipsMachine::set_stop_on_exception(enum ExceptionCause excause, bool value) {
+ if (cr != nullptr)
+ cr->set_stop_on_exception(excause, value);
+}
+
+bool QtMipsMachine::get_stop_on_exception(enum ExceptionCause excause) const {
+ if (cr != nullptr)
+ return cr->get_stop_on_exception(excause);
+ return false;
+}
+
+void QtMipsMachine::set_step_over_exception(enum ExceptionCause excause, bool value) {
+ if (cr != nullptr)
+ cr->set_step_over_exception(excause, value);
+}
+
+bool QtMipsMachine::get_step_over_exception(enum ExceptionCause excause) const {
+ if (cr != nullptr)
+ return cr->get_step_over_exception(excause);
+ return false;
+}
diff --git a/qtmips_machine/qtmipsmachine.h b/qtmips_machine/qtmipsmachine.h
index 349e0df..b90b96e 100644
--- a/qtmips_machine/qtmipsmachine.h
+++ b/qtmips_machine/qtmipsmachine.h
@@ -93,6 +93,10 @@ public:
void insert_hwbreak(std::uint32_t address);
void remove_hwbreak(std::uint32_t address);
bool is_hwbreak(std::uint32_t address);
+ void set_stop_on_exception(enum ExceptionCause excause, bool value);
+ bool get_stop_on_exception(enum ExceptionCause excause) const;
+ void set_step_over_exception(enum ExceptionCause excause, bool value);
+ bool get_step_over_exception(enum ExceptionCause excause) const;
public slots:
void play();