Looks like single step works.
authorTim Newsome <tim@sifive.com>
Thu, 10 Mar 2016 02:48:20 +0000 (18:48 -0800)
committerTim Newsome <tim@sifive.com>
Mon, 23 May 2016 19:12:09 +0000 (12:12 -0700)
riscv/execute.cc
riscv/gdbserver.cc
riscv/gdbserver.h
riscv/processor.cc
riscv/processor.h

index 45205b3d2ca1681f30bcc8740e8590356969d390..b6326004dca14a2a678bf4f40cdc0aabf71cd489 100644 (file)
@@ -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;
+  }
 }
index ea8b7d7e22d8aa4903f8bb14094759c8d9c96342..caea9185a2d4f121e5e3bd03f73ed869fecf2c2a 100644 (file)
@@ -445,6 +445,22 @@ void gdbserver_t::handle_continue(const std::vector<uint8_t> &packet)
   }
 
   p->set_halted(false);
+  running = true;
+}
+
+void gdbserver_t::handle_step(const std::vector<uint8_t> &packet)
+{
+  // s [addr]
+  processor_t *p = sim->get_core(0);
+  if (packet[2] != '#') {
+    std::vector<uint8_t>::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<uint8_t> &packet)
@@ -496,6 +512,8 @@ void gdbserver_t::handle_packet(const std::vector<uint8_t> &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();
index 4b34aef2856550dde5d7aa4c7a7550e3ffa9ad1c..178003d59718d9ede8d44c5e5945c2cb6a89ef31 100644 (file)
@@ -55,14 +55,15 @@ public:
   void handle_packet(const std::vector<uint8_t> &packet);
   void handle_interrupt();
 
-  void handle_halt_reason(const std::vector<uint8_t> &packet);
+  void handle_continue(const std::vector<uint8_t> &packet);
+  void handle_extended(const std::vector<uint8_t> &packet);
   void handle_general_registers_read(const std::vector<uint8_t> &packet);
-  void handle_memory_read(const std::vector<uint8_t> &packet);
+  void handle_halt_reason(const std::vector<uint8_t> &packet);
+  void handle_kill(const std::vector<uint8_t> &packet);
   void handle_memory_binary_write(const std::vector<uint8_t> &packet);
+  void handle_memory_read(const std::vector<uint8_t> &packet);
   void handle_register_read(const std::vector<uint8_t> &packet);
-  void handle_continue(const std::vector<uint8_t> &packet);
-  void handle_kill(const std::vector<uint8_t> &packet);
-  void handle_extended(const std::vector<uint8_t> &packet);
+  void handle_step(const std::vector<uint8_t> &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();
index 26a91dbc8bec6b4515267ca050c25c4ccb0c7d44..05fdb1c6f824be51e31e2531bd19190b9bd84a77 100644 (file)
@@ -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;
index 94e95939aebe547f492f8dd955beafeac6ec8e9c..e654c0fea2b8aec2830ba060c73e87a02eb47950 100644 (file)
@@ -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<insn_desc_t> instructions;