diff options
Diffstat (limited to 'qtmips_machine')
-rw-r--r-- | qtmips_machine/core.cpp | 47 | ||||
-rw-r--r-- | qtmips_machine/core.h | 6 | ||||
-rw-r--r-- | qtmips_machine/machineconfig.cpp | 51 | ||||
-rw-r--r-- | qtmips_machine/machineconfig.h | 13 | ||||
-rw-r--r-- | qtmips_machine/machinedefs.h | 1 | ||||
-rw-r--r-- | qtmips_machine/qtmipsmachine.cpp | 33 | ||||
-rw-r--r-- | qtmips_machine/qtmipsmachine.h | 4 |
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(); |