// Client can't take any more data right now.
break;
} else {
- printf("wrote %ld bytes: ", bytes);
+ fprintf(stderr, "wrote %ld bytes: ", bytes);
for (unsigned int i = 0; i < bytes; i++) {
- printf("%c", send_buf[i]);
+ fprintf(stderr, "%c", send_buf[i]);
}
- printf("\n");
+ fprintf(stderr, "\n");
send_buf.consume(bytes);
}
}
}
}
+typedef enum {
+ RC_XPR,
+ RC_PC,
+ RC_FPR,
+ RC_CSR
+} register_class_t;
+
+typedef struct {
+ register_class_t clss;
+ int index;
+} register_access_t;
+
+// gdb's register list is defined in riscv_gdb_reg_names gdb/riscv-tdep.c in
+// its source tree. The definition here must match that one.
+const register_access_t register_access[] = {
+ { RC_XPR, 0 },
+ { RC_XPR, 1 },
+ { RC_XPR, 2 },
+ { RC_XPR, 3 },
+ { RC_XPR, 4 },
+ { RC_XPR, 5 },
+ { RC_XPR, 6 },
+ { RC_XPR, 7 },
+ { RC_XPR, 8 },
+ { RC_XPR, 9 },
+ { RC_XPR, 10 },
+ { RC_XPR, 11 },
+ { RC_XPR, 12 },
+ { RC_XPR, 13 },
+ { RC_XPR, 14 },
+ { RC_XPR, 15 },
+ { RC_XPR, 16 },
+ { RC_XPR, 17 },
+ { RC_XPR, 18 },
+ { RC_XPR, 19 },
+ { RC_XPR, 20 },
+ { RC_XPR, 21 },
+ { RC_XPR, 22 },
+ { RC_XPR, 23 },
+ { RC_XPR, 24 },
+ { RC_XPR, 25 },
+ { RC_XPR, 26 },
+ { RC_XPR, 27 },
+ { RC_XPR, 28 },
+ { RC_XPR, 29 },
+ { RC_XPR, 30 },
+ { RC_XPR, 31 },
+ { RC_PC, 0 },
+ { RC_FPR, 0 },
+ { RC_FPR, 1 },
+ { RC_FPR, 2 },
+ { RC_FPR, 3 },
+ { RC_FPR, 4 },
+ { RC_FPR, 5 },
+ { RC_FPR, 6 },
+ { RC_FPR, 7 },
+ { RC_FPR, 8 },
+ { RC_FPR, 9 },
+ { RC_FPR, 10 },
+ { RC_FPR, 11 },
+ { RC_FPR, 12 },
+ { RC_FPR, 13 },
+ { RC_FPR, 14 },
+ { RC_FPR, 15 },
+ { RC_FPR, 16 },
+ { RC_FPR, 17 },
+ { RC_FPR, 18 },
+ { RC_FPR, 19 },
+ { RC_FPR, 20 },
+ { RC_FPR, 21 },
+ { RC_FPR, 22 },
+ { RC_FPR, 23 },
+ { RC_FPR, 24 },
+ { RC_FPR, 25 },
+ { RC_FPR, 26 },
+ { RC_FPR, 27 },
+ { RC_FPR, 28 },
+ { RC_FPR, 29 },
+ { RC_FPR, 30 },
+ { RC_FPR, 31 },
+
+#define DECLARE_CSR(name, num) { RC_CSR, num },
+#include "encoding.h"
+#undef DECLARE_CSR
+};
void gdbserver_t::handle_register_read(const std::vector<uint8_t> &packet)
{
// p n
- // Register order that gdb expects is:
- // "x0", "x1", "x2", "x3", "x4", "x5", "x6", "x7",
- // "x8", "x9", "x10", "x11", "x12", "x13", "x14", "x15",
- // "x16", "x17", "x18", "x19", "x20", "x21", "x22", "x23",
- // "x24", "x25", "x26", "x27", "x28", "x29", "x30", "x31",
- // "pc",
- // "f0", "f1", "f2", "f3", "f4", "f5", "f6", "f7",
- // "f8", "f9", "f10", "f11", "f12", "f13", "f14", "f15",
- // "f16", "f17", "f18", "f19", "f20", "f21", "f22", "f23",
- // "f24", "f25", "f26", "f27", "f28", "f29", "f30", "f31",
-
std::vector<uint8_t>::const_iterator iter = packet.begin() + 2;
unsigned int n = consume_hex_number(iter, packet.end());
if (*iter != '#')
return send_packet("E01");
+ if (n >= sizeof(register_access) / sizeof(*register_access))
+ return send_packet("E02");
+
processor_t *p = sim->get_core(0);
send("$");
running_checksum = 0;
- if (n < 32) {
- send(p->state.XPR[n]);
- } else if (n == 0x20) {
- send(p->state.pc);
- } else {
- send("E02");
+
+ register_access_t access = register_access[n];
+ switch (access.clss) {
+ case RC_XPR:
+ send(p->state.XPR[access.index]);
+ break;
+ case RC_PC:
+ send(p->state.pc);
+ break;
+ case RC_FPR:
+ send(p->state.FPR[access.index]);
+ break;
+ case RC_CSR:
+ try {
+ send(p->get_csr(access.index));
+ } catch(trap_t& t) {
+ send((reg_t) 0);
+ }
+ break;
}
send_running_checksum();
instruction = mmu->load_uint32(address);
mmu->store_uint32(address, EBREAK);
}
- printf(">>> Read %x from %lx\n", instruction, address);
+ fprintf(stderr, ">>> Read %x from %lx\n", instruction, address);
}
void software_breakpoint_t::remove(mmu_t* mmu)
{
- printf(">>> write %x to %lx\n", instruction, address);
+ fprintf(stderr, ">>> write %x to %lx\n", instruction, address);
if (size == 2) {
mmu->store_uint16(address, instruction);
} else {
consume_string(feature, iter, packet.end(), ';');
if (iter != packet.end())
iter++;
- printf("is %s supported?\n", feature.c_str());
if (feature == "swbreak+") {
send("swbreak+;");
}
return send_running_checksum();
}
- printf("Unsupported query %s\n", name.c_str());
+ fprintf(stderr, "Unsupported query %s\n", name.c_str());
return send_packet("");
}
self.gdb = testlib.Gdb()
self.gdb.command("file %s" % self.tmpf.name)
self.gdb.command("target extended-remote localhost:9824")
- self.gdb.command("p i");
self.gdb.command("p i=0");
def cleanUp(self):
self.assertIn("Continuing", output)
self.assertIn("Remote connection closed", output)
+ def test_registers(self):
+ output = self.gdb.command("info all-registers")
+ self.assertNotIn("Could not", output)
+ for reg in ('zero', 'ra', 'sp', 'gp', 'tp'):
+ self.assertIn(reg, output)
+ # mcpuid is one of the few registers that should have the high bit set
+ # (for rv64).
+ self.assertRegexpMatches(output, ".*mcpuid *0x80")
+
+ # The time register should always be changing.
+ last_time = None
+ for _ in range(5):
+ time = self.gdb.command("p $time").split('=')[-1]
+ self.assertNotEqual(time, last_time)
+ last_time = time
+ self.gdb.command("stepi")
+
if __name__ == '__main__':
unittest.main()