aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPavel Pisa <pisa@cmp.felk.cvut.cz>2019-03-06 23:40:34 +0100
committerPavel Pisa <pisa@cmp.felk.cvut.cz>2019-03-06 23:40:34 +0100
commit8d0f4806a7ad55710cb190e5a5c9388bd00c50a8 (patch)
tree16d5ac856513f44c4b1ecbccdebee151772f64e2
parent1536045c0d28113892abc9d1023ce395a0e82e94 (diff)
downloadqtmips-8d0f4806a7ad55710cb190e5a5c9388bd00c50a8.tar.gz
qtmips-8d0f4806a7ad55710cb190e5a5c9388bd00c50a8.tar.bz2
qtmips-8d0f4806a7ad55710cb190e5a5c9388bd00c50a8.zip
Enable configuration of syscalls emulation and stop on exception.
Signed-off-by: Pavel Pisa <pisa@cmp.felk.cvut.cz>
-rw-r--r--qtmips_gui/NewDialog.ui47
-rw-r--r--qtmips_gui/mainwindow.cpp20
-rw-r--r--qtmips_gui/newdialog.cpp32
-rw-r--r--qtmips_gui/newdialog.h5
-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
-rw-r--r--qtmips_osemu/ossyscall.cpp30
-rw-r--r--qtmips_osemu/ossyscall.h5
13 files changed, 270 insertions, 24 deletions
diff --git a/qtmips_gui/NewDialog.ui b/qtmips_gui/NewDialog.ui
index 411b075..1189e21 100644
--- a/qtmips_gui/NewDialog.ui
+++ b/qtmips_gui/NewDialog.ui
@@ -305,9 +305,52 @@
</attribute>
<layout class="QVBoxLayout" name="verticalLayout_7">
<item>
- <widget class="QCheckBox" name="osemu_enablecheck">
+ <widget class="QCheckBox" name="osemu_enable">
<property name="text">
- <string>Enable OS Emulation</string>
+ <string>Enable emulation of operating system services</string>
+ </property>
+ <property name="checked">
+ <bool>true</bool>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <widget class="QCheckBox" name="osemu_known_syscall_stop">
+ <property name="text">
+ <string>Stop on known system call</string>
+ </property>
+ <property name="checked">
+ <bool>true</bool>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <widget class="QCheckBox" name="osemu_unknown_syscall_stop">
+ <property name="text">
+ <string>Stop on unknown system call</string>
+ </property>
+ <property name="checked">
+ <bool>true</bool>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <widget class="QCheckBox" name="osemu_interrupt_stop">
+ <property name="text">
+ <string>Stop on interrupt entry</string>
+ </property>
+ <property name="checked">
+ <bool>true</bool>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <widget class="QCheckBox" name="osemu_exception_stop">
+ <property name="text">
+ <string>Stop and step over exceptions (overflow, etc.)</string>
+ </property>
+ <property name="checked">
+ <bool>true</bool>
</property>
</widget>
</item>
diff --git a/qtmips_gui/mainwindow.cpp b/qtmips_gui/mainwindow.cpp
index 3cefe94..d6d0b35 100644
--- a/qtmips_gui/mainwindow.cpp
+++ b/qtmips_gui/mainwindow.cpp
@@ -153,13 +153,21 @@ void MainWindow::create_core(const machine::MachineConfig &config) {
set_speed(); // Update machine speed to current settings
-#if 1
- osemu::OsSyscallExceptionHandler *osemu_handler = new osemu::OsSyscallExceptionHandler;
- machine->register_exception_handler(machine::EXCAUSE_SYSCALL, osemu_handler);
- connect(osemu_handler, SIGNAL(char_written(int,uint)), terminal, SLOT(tx_byte(int,uint)));
- connect(osemu_handler, SIGNAL(rx_byte_pool(int,uint&,bool&)),
+ if (config.osemu_enable()) {
+ osemu::OsSyscallExceptionHandler *osemu_handler =
+ new osemu::OsSyscallExceptionHandler(config.osemu_known_syscall_stop(),
+ config.osemu_unknown_syscall_stop());
+ machine->register_exception_handler(machine::EXCAUSE_SYSCALL, osemu_handler);
+ connect(osemu_handler, SIGNAL(char_written(int,uint)), terminal, SLOT(tx_byte(int,uint)));
+ connect(osemu_handler, SIGNAL(rx_byte_pool(int,uint&,bool&)),
terminal, SLOT(rx_byte_pool(int,uint&,bool&)));
-#endif
+ machine->set_step_over_exception(machine::EXCAUSE_SYSCALL, true);
+ machine->set_stop_on_exception(machine::EXCAUSE_SYSCALL, false);
+ } else {
+ machine->set_step_over_exception(machine::EXCAUSE_SYSCALL, false);
+ machine->set_stop_on_exception(machine::EXCAUSE_SYSCALL,
+ config.osemu_exception_stop());
+ }
// Connect machine signals and slots
connect(ui->actionRun, SIGNAL(triggered(bool)), machine, SLOT(play()));
diff --git a/qtmips_gui/newdialog.cpp b/qtmips_gui/newdialog.cpp
index 3e37357..53b2a05 100644
--- a/qtmips_gui/newdialog.cpp
+++ b/qtmips_gui/newdialog.cpp
@@ -72,6 +72,12 @@ NewDialog::NewDialog(QWidget *parent, QSettings *settings) : QDialog(parent) {
connect(ui->mem_time_write, SIGNAL(valueChanged(int)), this, SLOT(mem_time_write_change(int)));
connect(ui->mem_time_burst, SIGNAL(valueChanged(int)), this, SLOT(mem_time_burst_change(int)));
+ connect(ui->osemu_enable, SIGNAL(clicked(bool)), this, SLOT(osemu_enable_change(bool)));
+ connect(ui->osemu_known_syscall_stop, SIGNAL(clicked(bool)), this, SLOT(osemu_known_syscall_stop_change(bool)));
+ connect(ui->osemu_unknown_syscall_stop, SIGNAL(clicked(bool)), this, SLOT(osemu_unknown_syscall_stop_change(bool)));
+ connect(ui->osemu_interrupt_stop, SIGNAL(clicked(bool)), this, SLOT(osemu_interrupt_stop_change(bool)));
+ connect(ui->osemu_exception_stop, SIGNAL(clicked(bool)), this, SLOT(osemu_exception_stop_change(bool)));
+
cache_handler_d = new NewDialogCacheHandler(this, ui_cache_d);
cache_handler_p = new NewDialogCacheHandler(this, ui_cache_p);
@@ -196,6 +202,26 @@ void NewDialog::mem_time_burst_change(int v) {
}
}
+void NewDialog::osemu_enable_change(bool v) {
+ config->set_osemu_enable(v);
+}
+
+void NewDialog::osemu_known_syscall_stop_change(bool v) {
+ config->set_osemu_known_syscall_stop(v);
+}
+
+void NewDialog::osemu_unknown_syscall_stop_change(bool v) {
+ config->set_osemu_unknown_syscall_stop(v);
+}
+
+void NewDialog::osemu_interrupt_stop_change(bool v) {
+ config->set_osemu_interrupt_stop(v);
+}
+
+void NewDialog::osemu_exception_stop_change(bool v) {
+ config->set_osemu_exception_stop(v);
+}
+
void NewDialog::config_gui() {
// Basic
ui->elf_file->setText(config->elf());
@@ -214,6 +240,12 @@ void NewDialog::config_gui() {
// Cache
cache_handler_d->config_gui();
cache_handler_p->config_gui();
+ // Operating system and exceptions
+ ui->osemu_enable->setChecked(config->osemu_enable());
+ ui->osemu_known_syscall_stop->setChecked(config->osemu_known_syscall_stop());
+ ui->osemu_unknown_syscall_stop->setChecked(config->osemu_unknown_syscall_stop());
+ ui->osemu_interrupt_stop->setChecked(config->osemu_interrupt_stop());
+ ui->osemu_exception_stop->setChecked(config->osemu_exception_stop());
// Disable various sections according to configuration
ui->delay_slot->setEnabled(!config->pipelined());
diff --git a/qtmips_gui/newdialog.h b/qtmips_gui/newdialog.h
index 2b1b7c4..edd633e 100644
--- a/qtmips_gui/newdialog.h
+++ b/qtmips_gui/newdialog.h
@@ -70,6 +70,11 @@ private slots:
void mem_time_read_change(int);
void mem_time_write_change(int);
void mem_time_burst_change(int);
+ void osemu_enable_change(bool);
+ void osemu_known_syscall_stop_change(bool);
+ void osemu_unknown_syscall_stop_change(bool);
+ void osemu_interrupt_stop_change(bool);
+ void osemu_exception_stop_change(bool);
private:
Ui::NewDialog *ui;
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();
diff --git a/qtmips_osemu/ossyscall.cpp b/qtmips_osemu/ossyscall.cpp
index aeee079..fed4548 100644
--- a/qtmips_osemu/ossyscall.cpp
+++ b/qtmips_osemu/ossyscall.cpp
@@ -60,7 +60,7 @@ struct mips_syscall_desc_t {
&OsSyscallExceptionHandler::handler},
static const mips_syscall_desc_t mips_syscall_args[] = {
MIPS_SYS(sys_syscall , 8, syscall_default_handler) /* 4000 */
- MIPS_SYS(sys_exit , 1, syscall_default_handler)
+ MIPS_SYS(sys_exit , 1, do_sys_exit)
MIPS_SYS(sys_fork , 0, syscall_default_handler)
MIPS_SYS(sys_read , 3, do_sys_read)
MIPS_SYS(sys_write , 3, do_sys_write)
@@ -427,10 +427,13 @@ static const mips_syscall_desc_t mips_syscall_args[] = {
const unsigned mips_syscall_args_size =
sizeof(mips_syscall_args)/sizeof(*mips_syscall_args);
-OsSyscallExceptionHandler::OsSyscallExceptionHandler() {
+OsSyscallExceptionHandler::OsSyscallExceptionHandler(bool known_syscall_stop,
+ bool unknown_syscall_stop) {
brk_limit = 0;
anonymous_base = 0x60000000;
anonymous_last = anonymous_base;
+ this->known_syscall_stop = known_syscall_stop;
+ this->unknown_syscall_stop = unknown_syscall_stop;
}
bool OsSyscallExceptionHandler::handle_exception(Core *core, Registers *regs,
@@ -496,7 +499,8 @@ bool OsSyscallExceptionHandler::handle_exception(Core *core, Registers *regs,
#endif
status = (this->*sdesc->handler)(result, core, syscall_num,
a1, a2, a3, a4, a5, a6, a7, a8);
- emit core->stop_on_exception_reached();
+ if (known_syscall_stop)
+ emit core->stop_on_exception_reached();
regs->write_gp(7, status);
if (status < 0)
@@ -524,6 +528,26 @@ int OsSyscallExceptionHandler::syscall_default_handler(std::uint32_t &result, Co
(void)core; (void)syscall_num;
(void)a1; (void)a2; (void)a3; (void)a4; (void)a5; (void)a6; (void)a7; (void)a8;
result = 0;
+ if (unknown_syscall_stop)
+ emit core->stop_on_exception_reached();
+ return 0;
+}
+
+// void exit(int status);
+int OsSyscallExceptionHandler::do_sys_exit(std::uint32_t &result, Core *core,
+ std::uint32_t syscall_num,
+ std::uint32_t a1, std::uint32_t a2, std::uint32_t a3,
+ std::uint32_t a4, std::uint32_t a5, std::uint32_t a6,
+ std::uint32_t a7, std::uint32_t a8) {
+ (void)core; (void)syscall_num;
+ (void)a1; (void)a2; (void)a3; (void)a4; (void)a5; (void)a6; (void)a7; (void)a8;
+
+ result = 0;
+ int status = a1;
+
+ printf("sys_exit status %d\n", status);
+ emit core->stop_on_exception_reached();
+
return 0;
}
diff --git a/qtmips_osemu/ossyscall.h b/qtmips_osemu/ossyscall.h
index 0c02699..bcb202f 100644
--- a/qtmips_osemu/ossyscall.h
+++ b/qtmips_osemu/ossyscall.h
@@ -57,12 +57,13 @@ int name(std::uint32_t &result, machine::Core *core, \
class OsSyscallExceptionHandler : public machine::ExceptionHandler {
Q_OBJECT
public:
- OsSyscallExceptionHandler();
+ OsSyscallExceptionHandler(bool known_syscall_stop = false, bool unknown_syscall_stop = false);
bool handle_exception(machine::Core *core, machine::Registers *regs,
machine::ExceptionCause excause, std::uint32_t inst_addr,
std::uint32_t next_addr, std::uint32_t jump_branch_pc,
bool in_delay_slot, std::uint32_t mem_ref_addr);
OSSYCALL_HANDLER_DECLARE(syscall_default_handler);
+ OSSYCALL_HANDLER_DECLARE(do_sys_exit);
OSSYCALL_HANDLER_DECLARE(do_sys_set_thread_area);
OSSYCALL_HANDLER_DECLARE(do_sys_writev);
OSSYCALL_HANDLER_DECLARE(do_sys_write);
@@ -77,6 +78,8 @@ private:
std::uint32_t brk_limit;
std::uint32_t anonymous_base;
std::uint32_t anonymous_last;
+ bool known_syscall_stop;
+ bool unknown_syscall_stop;
};
#undef OSSYCALL_HANDLER_DECLARE