diff options
-rw-r--r-- | qtmips_gui/mainwindow.cpp | 2 | ||||
-rw-r--r-- | qtmips_gui/terminaldock.cpp | 17 | ||||
-rw-r--r-- | qtmips_gui/terminaldock.h | 4 | ||||
-rw-r--r-- | qtmips_machine/serialport.cpp | 22 | ||||
-rw-r--r-- | qtmips_machine/serialport.h | 5 | ||||
-rw-r--r-- | qtmips_osemu/ossyscall.cpp | 81 | ||||
-rw-r--r-- | qtmips_osemu/ossyscall.h | 3 |
7 files changed, 130 insertions, 4 deletions
diff --git a/qtmips_gui/mainwindow.cpp b/qtmips_gui/mainwindow.cpp index 253ab03..01321cf 100644 --- a/qtmips_gui/mainwindow.cpp +++ b/qtmips_gui/mainwindow.cpp @@ -154,6 +154,8 @@ void MainWindow::create_core(const machine::MachineConfig &config) { 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&)), + terminal, SLOT(rx_byte_pool(int,uint&,bool&))); #endif // Connect machine signals and slots diff --git a/qtmips_gui/terminaldock.cpp b/qtmips_gui/terminaldock.cpp index 4b394a6..bb26952 100644 --- a/qtmips_gui/terminaldock.cpp +++ b/qtmips_gui/terminaldock.cpp @@ -49,6 +49,11 @@ TerminalDock::TerminalDock(QWidget *parent, QSettings *settings) : QDockWidget(p terminal_text->setMinimumSize(30, 30); layout_box->addWidget(terminal_text); append_cursor = new QTextCursor(terminal_text->document()); + layout_bottom_box = new QHBoxLayout(); + layout_bottom_box->addWidget(new QLabel("Input:")); + input_edit = new QLineEdit(); + layout_bottom_box->addWidget(input_edit); + layout_box->addLayout(layout_bottom_box); setObjectName("Terminal"); setWindowTitle("Terminal"); @@ -62,6 +67,8 @@ void TerminalDock::setup(const machine::SerialPort *ser_port) { if (ser_port == nullptr) return; connect(ser_port, SIGNAL(tx_byte(uint)), this, SLOT(tx_byte(uint))); + connect(ser_port, SIGNAL(rx_byte_pool(int,uint&,bool&)), + this, SLOT(rx_byte_pool(int,uint&,bool&))); } void TerminalDock::tx_byte(unsigned int data) { @@ -76,3 +83,13 @@ void TerminalDock::tx_byte(int fd, unsigned int data) (void)fd; tx_byte(data); } + +void TerminalDock::rx_byte_pool(int fd, unsigned int &data, bool &available) { + QString str = input_edit->text(); + available = false; + if (str.count() > 0) { + data = str[0].toLatin1(); + input_edit->setText(str.remove(0, 1)); + available = true; + } +} diff --git a/qtmips_gui/terminaldock.h b/qtmips_gui/terminaldock.h index 7154e81..27dc617 100644 --- a/qtmips_gui/terminaldock.h +++ b/qtmips_gui/terminaldock.h @@ -39,6 +39,7 @@ #include <QDockWidget> #include <QLabel> #include <QFormLayout> +#include <QLineEdit> #include <QTextEdit> #include <QTextCursor> #include "qtmipsmachine.h" @@ -54,13 +55,16 @@ public: public slots: void tx_byte(unsigned int data); void tx_byte(int fd, unsigned int data); + void rx_byte_pool(int fd, unsigned int &data, bool &available); private: QVBoxLayout *layout_box; + QHBoxLayout *layout_bottom_box; QWidget *top_widget, *top_form; QFormLayout *layout_top_form; QTextEdit *terminal_text; QTextCursor *append_cursor; + QLineEdit *input_edit; }; #endif // TERMINALDOCK_H diff --git a/qtmips_machine/serialport.cpp b/qtmips_machine/serialport.cpp index 9e4177b..c636d38 100644 --- a/qtmips_machine/serialport.cpp +++ b/qtmips_machine/serialport.cpp @@ -51,6 +51,7 @@ using namespace machine; SerialPort::SerialPort() { rx_st_reg = 0; + rx_data_reg = 0; tx_st_reg = 0; } @@ -58,6 +59,18 @@ SerialPort::~SerialPort() { } +void SerialPort::pool_rx_byte() const { + unsigned int byte = 0; + bool available = false; + if (!(rx_st_reg & SERP_RX_ST_REG_READY_m)) { + emit rx_byte_pool(0, byte, available); + if (available) { + rx_data_reg = byte; + rx_st_reg |= SERP_RX_ST_REG_READY_m; + } + } +} + bool SerialPort::wword(std::uint32_t address, std::uint32_t value) { #if 0 printf("SerialPort::wword address 0x%08lx data 0x%08lx\n", @@ -90,10 +103,17 @@ std::uint32_t SerialPort::rword(std::uint32_t address, bool debug_access) const #endif switch (address) { case SERP_RX_ST_REG_o: + pool_rx_byte(); value = rx_st_reg; break; case SERP_RX_DATA_REG_o: - value = 0; + pool_rx_byte(); + if (rx_st_reg & SERP_RX_ST_REG_READY_m) { + value = rx_data_reg; + rx_st_reg &= ~SERP_RX_ST_REG_READY_m; + } else { + value = 0; + } break; case SERP_TX_ST_REG_o: value = tx_st_reg | SERP_TX_ST_REG_READY_m; diff --git a/qtmips_machine/serialport.h b/qtmips_machine/serialport.h index add1fe6..5262720 100644 --- a/qtmips_machine/serialport.h +++ b/qtmips_machine/serialport.h @@ -52,6 +52,7 @@ public: signals: void tx_byte(unsigned int data); + void rx_byte_pool(int fd, unsigned int &data, bool &available) const; void write_notification(std::uint32_t address, std::uint32_t value); void read_notification(std::uint32_t address, std::uint32_t *value) const; @@ -59,7 +60,9 @@ public: bool wword(std::uint32_t address, std::uint32_t value); std::uint32_t rword(std::uint32_t address, bool debug_access = false) const; private: - std::uint32_t rx_st_reg; + void pool_rx_byte() const; + mutable std::uint32_t rx_st_reg; + mutable std::uint32_t rx_data_reg; std::uint32_t tx_st_reg; }; diff --git a/qtmips_osemu/ossyscall.cpp b/qtmips_osemu/ossyscall.cpp index a5748f1..aeee079 100644 --- a/qtmips_osemu/ossyscall.cpp +++ b/qtmips_osemu/ossyscall.cpp @@ -62,7 +62,7 @@ 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_fork , 0, syscall_default_handler) - MIPS_SYS(sys_read , 3, syscall_default_handler) + MIPS_SYS(sys_read , 3, do_sys_read) MIPS_SYS(sys_write , 3, do_sys_write) MIPS_SYS(sys_open , 3, syscall_default_handler) /* 4005 */ MIPS_SYS(sys_close , 1, syscall_default_handler) @@ -204,7 +204,7 @@ static const mips_syscall_desc_t mips_syscall_args[] = { MIPS_SYS(sys_select , 5, syscall_default_handler) MIPS_SYS(sys_flock , 2, syscall_default_handler) MIPS_SYS(sys_msync , 3, syscall_default_handler) - MIPS_SYS(sys_readv , 3, syscall_default_handler) /* 4145 */ + MIPS_SYS(sys_readv , 3, do_sys_readv) /* 4145 */ MIPS_SYS(sys_writev , 3, do_sys_writev) MIPS_SYS(sys_cacheflush , 3, syscall_default_handler) MIPS_SYS(sys_cachectl , 3, syscall_default_handler) @@ -598,6 +598,83 @@ int OsSyscallExceptionHandler::do_sys_write(std::uint32_t &result, Core *core, return 0; } +// ssize_t readv(int fd, const struct iovec *iov, int iovcnt); +int OsSyscallExceptionHandler::do_sys_readv(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 fd = a1; + std::uint32_t iov = a2; + int iovcnt = a3; + MemoryAccess *mem = core->get_mem_data(); + bool available; + unsigned int byte; + + printf("sys_readv to fd %d\n", fd); + + while (iovcnt-- > 0) { + std::uint32_t iov_base = mem->read_word(iov); + std::uint32_t iov_len = mem->read_word(iov + 4); + iov += 8; + available = true; + for (std::uint32_t i = 0; i < iov_len; i++) { + emit rx_byte_pool(fd, byte, available); + if (!available) { + // add final newline if there are no more data + mem->write_byte(iov_base++, '\n'); + result += 1; + break; + } + mem->write_byte(iov_base++, byte); + result += 1; + } + if (!available) + break; + } + + return 0; +} + +// ssize_t read(int fd, void *buf, size_t count); +int OsSyscallExceptionHandler::do_sys_read(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 fd = a1; + std::uint32_t buf = a2; + int size = a3; + MemoryAccess *mem = core->get_mem_data(); + bool available; + unsigned int byte; + + printf("sys_read to fd %d\n", fd); + + result = 0; + while (size-- > 0) { + emit rx_byte_pool(fd, byte, available); + if (!available) { + // add final newline if there are no more data + mem->write_byte(buf++, '\n'); + result += 1; + break; + } + mem->write_byte(buf++, byte); + result += 1; + } + + return 0; +} + // int or void * brk(void *addr); int OsSyscallExceptionHandler::do_sys_brk(std::uint32_t &result, Core *core, std::uint32_t syscall_num, diff --git a/qtmips_osemu/ossyscall.h b/qtmips_osemu/ossyscall.h index 00b6575..0c02699 100644 --- a/qtmips_osemu/ossyscall.h +++ b/qtmips_osemu/ossyscall.h @@ -66,10 +66,13 @@ public: OSSYCALL_HANDLER_DECLARE(do_sys_set_thread_area); OSSYCALL_HANDLER_DECLARE(do_sys_writev); OSSYCALL_HANDLER_DECLARE(do_sys_write); + OSSYCALL_HANDLER_DECLARE(do_sys_readv); + OSSYCALL_HANDLER_DECLARE(do_sys_read); OSSYCALL_HANDLER_DECLARE(do_sys_brk); OSSYCALL_HANDLER_DECLARE(do_sys_mmap2); signals: void char_written(int fd, unsigned int val); + void rx_byte_pool(int fd, unsigned int &data, bool &available); private: std::uint32_t brk_limit; std::uint32_t anonymous_base; |