+////////////////////////////// Debug Operations
+
+class halt_op_t : public operation_t
+{
+ public:
+ halt_op_t(gdbserver_t& gdbserver) : operation_t(gdbserver) {};
+
+ bool start()
+ {
+ // TODO: For now we just assume the target is 64-bit.
+ gs.write_debug_ram(0, csrsi(DCSR_ADDRESS, DCSR_HALT_MASK));
+ gs.write_debug_ram(1, csrr(S0, DPC_ADDRESS));
+ gs.write_debug_ram(2, sd(S0, 0, (uint16_t) DEBUG_RAM_START));
+ gs.write_debug_ram(3, csrr(S0, DCSR_ADDRESS));
+ gs.write_debug_ram(4, sd(S0, 0, (uint16_t) DEBUG_RAM_START + 8));
+ gs.write_debug_ram(5, jal(0, (uint32_t) (DEBUG_ROM_RESUME - (DEBUG_RAM_START + 4*5))));
+ gs.set_interrupt(0);
+ return false;
+ }
+
+ bool step()
+ {
+ return true;
+ }
+};
+
+class general_registers_read_op_t : public operation_t
+{
+ // 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",
+
+ // Each byte of register data is described by two hex digits. The bytes with
+ // the register are transmitted in target byte order. The size of each
+ // register and their position within the āgā packet are determined by the
+ // gdb internal gdbarch functions DEPRECATED_REGISTER_RAW_SIZE and
+ // gdbarch_register_name.
+
+ public:
+ general_registers_read_op_t(gdbserver_t& gdbserver) :
+ operation_t(gdbserver), current_reg(0) {};
+
+ bool start()
+ {
+ gs.start_packet();
+
+ // x0 is always zero.
+ gs.send((reg_t) 0);
+
+ gs.write_debug_ram(0, sd(1, 0, (uint16_t) DEBUG_RAM_START + 16));
+ gs.write_debug_ram(1, sd(2, 0, (uint16_t) DEBUG_RAM_START + 0));
+ gs.write_debug_ram(2, jal(0, (uint32_t) (DEBUG_ROM_RESUME - (DEBUG_RAM_START + 4*2))));
+ gs.set_interrupt(0);
+ current_reg = 1;
+ return false;
+ }
+
+ bool step()
+ {
+ fprintf(stderr, "step %d\n", current_reg);
+ gs.send(((uint64_t) gs.read_debug_ram(5) << 32) | gs.read_debug_ram(4));
+ if (current_reg >= 31) {
+ gs.end_packet();
+ return true;
+ }
+
+ gs.send(((uint64_t) gs.read_debug_ram(1) << 32) | gs.read_debug_ram(0));
+
+ current_reg += 2;
+ // TODO properly read s0 and s1
+ gs.write_debug_ram(0, sd(current_reg, 0, (uint16_t) DEBUG_RAM_START + 16));
+ gs.write_debug_ram(1, sd(current_reg+1, 0, (uint16_t) DEBUG_RAM_START + 0));
+ gs.write_debug_ram(2, jal(0, (uint32_t) (DEBUG_ROM_RESUME - (DEBUG_RAM_START + 4*2))));
+ gs.set_interrupt(0);
+
+ return false;
+ }
+
+ private:
+ unsigned int current_reg;
+};
+
+class register_read_op_t : public operation_t
+{
+ public:
+ register_read_op_t(gdbserver_t& gdbserver, unsigned int reg) :
+ operation_t(gdbserver), reg(reg) {};
+
+ bool start()
+ {
+ if (reg >= REG_XPR0 && reg <= REG_XPR31) {
+ die("handle_register_read");
+ // send(p->state.XPR[reg - REG_XPR0]);
+ } else if (reg == REG_PC) {
+ gs.write_debug_ram(0, csrr(S0, DPC_ADDRESS));
+ gs.write_debug_ram(1, sd(S0, 0, (uint16_t) DEBUG_RAM_START));
+ gs.write_debug_ram(2, jal(0, (uint32_t) (DEBUG_ROM_RESUME - (DEBUG_RAM_START + 4*2))));
+ gs.set_interrupt(0);
+ } else if (reg >= REG_FPR0 && reg <= REG_FPR31) {
+ die("handle_register_read");
+ // send(p->state.FPR[reg - REG_FPR0]);
+ } else if (reg >= REG_CSR0 && reg <= REG_CSR4095) {
+ try {
+ die("handle_register_read");
+ // send(p->get_csr(reg - REG_CSR0));
+ } catch(trap_t& t) {
+ // It would be nicer to return an error here, but if you do that then gdb
+ // exits out of 'info registers all' as soon as it encounters a register
+ // that can't be read.
+ gs.start_packet();
+ gs.send((reg_t) 0);
+ gs.end_packet();
+ }
+ } else {
+ gs.send_packet("E02");
+ return true;
+ }
+
+ return false;
+ }
+
+ bool step()
+ {
+ gs.start_packet();
+ gs.send(((uint64_t) gs.read_debug_ram(1) << 32) | gs.read_debug_ram(0));
+ gs.end_packet();
+ return true;
+ }
+
+ private:
+ unsigned int reg;
+};
+
+////////////////////////////// gdbserver itself
+