From 6f9a128a448e4043ab6255261d73d26acc723f5d Mon Sep 17 00:00:00 2001 From: Tim Newsome Date: Wed, 9 Mar 2016 18:48:20 -0800 Subject: [PATCH] Looks like single step works. --- riscv/execute.cc | 15 ++++++++++++++- riscv/gdbserver.cc | 27 +++++++++++++++++++++++++++ riscv/gdbserver.h | 14 +++++++++----- riscv/processor.cc | 7 ++++++- riscv/processor.h | 4 ++++ 5 files changed, 60 insertions(+), 7 deletions(-) diff --git a/riscv/execute.cc b/riscv/execute.cc index 45205b3..b632600 100644 --- a/riscv/execute.cc +++ b/riscv/execute.cc @@ -55,7 +55,15 @@ void processor_t::step(size_t n) { // TODO: We should really not call this function at all when halted, to avoid // burning CPU. - while (run && !halted && n > 0) { + if (single_step) { + halted = false; + n = 1; + } + if (halted) { + return; + } + + while (run && n > 0) { size_t instret = 0; reg_t pc = state.pc; mmu_t* _mmu = mmu; @@ -128,4 +136,9 @@ miss: state.minstret += instret; n -= instret; } + + if (single_step) { + single_step = false; + halted = true; + } } diff --git a/riscv/gdbserver.cc b/riscv/gdbserver.cc index ea8b7d7..caea918 100644 --- a/riscv/gdbserver.cc +++ b/riscv/gdbserver.cc @@ -445,6 +445,22 @@ void gdbserver_t::handle_continue(const std::vector &packet) } p->set_halted(false); + running = true; +} + +void gdbserver_t::handle_step(const std::vector &packet) +{ + // s [addr] + processor_t *p = sim->get_core(0); + if (packet[2] != '#') { + std::vector::const_iterator iter = packet.begin() + 2; + p->state.pc = consume_hex_number(iter, packet.end()); + if (*iter != '#') + return send_packet("E16"); // EINVAL + } + + p->set_single_step(true); + running = true; } void gdbserver_t::handle_kill(const std::vector &packet) @@ -496,6 +512,8 @@ void gdbserver_t::handle_packet(const std::vector &packet) return handle_register_read(packet); case 'c': return handle_continue(packet); + case 's': + return handle_step(packet); } // Not supported. @@ -509,10 +527,19 @@ void gdbserver_t::handle_interrupt() processor_t *p = sim->get_core(0); p->set_halted(true); send_packet("S02"); // Pretend program received SIGINT. + running = false; } void gdbserver_t::handle() { + processor_t *p = sim->get_core(0); + if (running && p->halted) { + // The core was running, but now it's halted. Better tell gdb. + send_packet("T00"); + // TODO: Actually include register values here + running = false; + } + if (client_fd > 0) { this->read(); this->write(); diff --git a/riscv/gdbserver.h b/riscv/gdbserver.h index 4b34aef..178003d 100644 --- a/riscv/gdbserver.h +++ b/riscv/gdbserver.h @@ -55,14 +55,15 @@ public: void handle_packet(const std::vector &packet); void handle_interrupt(); - void handle_halt_reason(const std::vector &packet); + void handle_continue(const std::vector &packet); + void handle_extended(const std::vector &packet); void handle_general_registers_read(const std::vector &packet); - void handle_memory_read(const std::vector &packet); + void handle_halt_reason(const std::vector &packet); + void handle_kill(const std::vector &packet); void handle_memory_binary_write(const std::vector &packet); + void handle_memory_read(const std::vector &packet); void handle_register_read(const std::vector &packet); - void handle_continue(const std::vector &packet); - void handle_kill(const std::vector &packet); - void handle_extended(const std::vector &packet); + void handle_step(const std::vector &packet); private: sim_t *sim; @@ -73,6 +74,9 @@ private: bool expect_ack; bool extended_mode; + // Used to track whether we think the target is running. If we think it is + // but it isn't, we need to tell gdb about it. + bool running; // Read pending data from the client. void read(); diff --git a/riscv/processor.cc b/riscv/processor.cc index 26a91db..05fdb1c 100644 --- a/riscv/processor.cc +++ b/riscv/processor.cc @@ -22,7 +22,7 @@ processor_t::processor_t(const char* isa, sim_t* sim, uint32_t id) : sim(sim), ext(NULL), disassembler(new disassembler_t), - id(id), run(false), debug(false), halted(false) + id(id), run(false), debug(false), halted(false), single_step(false) { parse_isa_string(isa); @@ -131,6 +131,11 @@ void processor_t::set_halted(bool value) halted = value; } +void processor_t::set_single_step(bool value) +{ + single_step = value; +} + void processor_t::set_histogram(bool value) { histogram_enabled = value; diff --git a/riscv/processor.h b/riscv/processor.h index 94e9593..e654c0f 100644 --- a/riscv/processor.h +++ b/riscv/processor.h @@ -82,6 +82,7 @@ public: void set_debug(bool value); void set_halted(bool value); + void set_single_step(bool value); void set_histogram(bool value); void reset(bool value); void step(size_t n); // run for n cycles @@ -123,6 +124,9 @@ private: bool debug; // TODO: Should this just be rolled into `run`? bool halted; // When true, no instructions are executed. + // When true, execute exactly one instruction (even if halted is true), then + // set halted to true and single_step to false. + bool single_step; bool histogram_enabled; std::vector instructions; -- 2.30.2