Skip to content

Commit 7683be6

Browse files
committed
Implemented missing step instructions
1 parent c580358 commit 7683be6

File tree

6 files changed

+101
-20
lines changed

6 files changed

+101
-20
lines changed

src/crt0.asm

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ global __SYSVAR_BORDCR
1010
global _clear42
1111
global _print42
1212
global module_header
13+
global nmi_handler
1314
extern gdbserver_install
1415

1516
defc INITIAL_SP = 0xFFFF

src/install.asm

Lines changed: 22 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -68,7 +68,7 @@ rst8h_handler_src:
6868
rst8h_handler_src_end:
6969

7070
STR_installed:
71-
defb "*** GDBSERVER INSTALLED ***\nPress NMI, then attach on port 1667.\n", 0
71+
defb "*** GDBSERVER v0.2 INSTALLED ***\nPress NMI, then attach on port 1667.\n", 0
7272

7373
STR_install_error:
7474
defb "Cannot install. Make sure your spectranet firmware is updated.\n", 0
@@ -116,12 +116,29 @@ gdbserver_install_ok:
116116

117117
jp EXIT_SUCCESS
118118

119-
global _restore_rst08h
120-
_restore_rst08h:
119+
global _gdbserver_trap
120+
_gdbserver_trap:
121+
# one time only
122+
call DISABLETRAP
123+
124+
# restore rst8 on a breakpoint
125+
ld a, (gdbserver_trap_flags)
126+
and 0x01
127+
jr z, gdbserver_trap_skip_restore_rst08
128+
121129
# load instruction address
122130
ld hl, (gdbserver_trap_handler+5)
123131
# put rst 08 back
124132
ld (hl), 0xCF
125-
# one time only
126-
call DISABLETRAP
133+
gdbserver_trap_skip_restore_rst08:
134+
135+
# do a single instruction
136+
ld a, (gdbserver_trap_flags)
137+
and 0x02
138+
jr z, gdbserver_trap_skip_trigger_step
139+
# launch the debugger
140+
extern nmi_handler
141+
call nmi_handler
142+
gdbserver_trap_skip_trigger_step:
143+
127144
jp PAGETRAPRETURN

src/modulecall.c

Lines changed: 38 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44
#include "state.h"
55
#include "sockpoll.h"
66

7-
extern void restore_rst08h();
7+
extern void gdbserver_trap();
88

99
void modulecall()
1010
{
@@ -19,26 +19,38 @@ void modulecall()
1919
return;
2020
}
2121

22+
// reset breaking
23+
gdbserver_state.trap_flags = 0;
24+
2225
struct breakpoint_t* trapped_breakpoint = NULL;
26+
uint16_t* pc = &gdbserver_state.registers[REGISTERS_PC];
2327

2428
if (gdbserver_state.client_socket)
2529
{
2630
print42("execution stopped\n");
27-
uint16_t* pc = &gdbserver_state.registers[REGISTERS_PC];
28-
29-
// unwind RST08
30-
(*pc)--;
3131

32-
for (uint8_t i = 0; i < MAX_BREAKPOINTS_COUNT; i++)
32+
if (gdbserver_state.temporary_breakpoint.address == (*pc - 1))
3333
{
34-
struct breakpoint_t* b = &gdbserver_state.breakpoints[i];
35-
if (b->address == *pc)
34+
// we've hit temp breakpoint, original instruction
35+
// note, we do not put RST08 back, because it is temporary
36+
*(uint8_t*)gdbserver_state.temporary_breakpoint.address =
37+
gdbserver_state.temporary_breakpoint.original_instruction;
38+
// unwind RST08
39+
(*pc)--;
40+
}
41+
else
42+
{
43+
for (uint8_t i = 0; i < MAX_BREAKPOINTS_COUNT; i++)
3644
{
37-
trapped_breakpoint = b;
45+
struct breakpoint_t* b = &gdbserver_state.breakpoints[i];
46+
if (b->address == (*pc - 1)) // offset for RST08
47+
{
48+
trapped_breakpoint = b;
3849

39-
// restore original instruction
40-
*(uint8_t*)b->address = b->original_instruction;
41-
break;
50+
// restore original instruction
51+
*(uint8_t*)b->address = b->original_instruction;
52+
break;
53+
}
4254
}
4355
}
4456

@@ -53,6 +65,12 @@ void modulecall()
5365
}
5466
}
5567

68+
if (trapped_breakpoint)
69+
{
70+
// unwind RST08
71+
(*pc)--;
72+
}
73+
5674
while (1)
5775
{
5876
switch (poll_fd(gdbserver_state.client_socket))
@@ -83,13 +101,18 @@ void modulecall()
83101
done:
84102
print42("resuming execution\n");
85103

86-
// we have to restore RST08 on the breakpoint
87104
if (trapped_breakpoint && trapped_breakpoint->address == gdbserver_state.registers[REGISTERS_PC])
105+
{
106+
// we have to restore RST08 on the breakpoint
107+
gdbserver_state.trap_flags |= TRAP_FLAG_RESTORE_RST08H;
108+
}
109+
110+
if (gdbserver_state.trap_flags)
88111
{
89112
gdbserver_state.trap_handler.page = 0xFF;
90-
gdbserver_state.trap_handler.address = trapped_breakpoint->address;
113+
gdbserver_state.trap_handler.address = *pc;
91114
gdbserver_state.trap_handler.next_address = 0x0000;
92-
gdbserver_state.trap_handler.handler = (uint16_t)restore_rst08h;
115+
gdbserver_state.trap_handler.handler = (uint16_t)gdbserver_trap;
93116

94117
set_trap(&gdbserver_state.trap_handler);
95118
}

src/server.c

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -122,6 +122,32 @@ static uint8_t process_packet()
122122
// continue execution
123123
return 0;
124124
}
125+
case 's':
126+
{
127+
// do one step
128+
gdbserver_state.trap_flags |= TRAP_FLAG_STEP_INSTRUCTION;
129+
return 0;
130+
}
131+
case 'i':
132+
{
133+
// step over calls
134+
uint8_t offset = *payload - '0'; // simple atoi
135+
136+
uint16_t address = gdbserver_state.registers[REGISTERS_PC] + offset;
137+
gdbserver_state.temporary_breakpoint.address = address;
138+
gdbserver_state.temporary_breakpoint.original_instruction = *(uint8_t*)address;
139+
140+
*(uint8_t*)address = 0xCF; // RST 08h
141+
142+
if (*(uint8_t*)address != 0xCF)
143+
{
144+
// write didn't do anything, probably read only
145+
gdbserver_state.temporary_breakpoint.address = 0;
146+
// so trip as soon as we can
147+
gdbserver_state.trap_flags |= TRAP_FLAG_STEP_INSTRUCTION;
148+
}
149+
return 0;
150+
}
125151
case 'q':
126152
{
127153
if (strstr(payload, "Xfer:features:read") == payload)

src/state.h

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,24 +20,37 @@ struct breakpoint_t {
2020

2121
/*
2222
* Beware, only 1021 bytes are available
23+
* Offsets of these are crucial
2324
*/
2425
struct gdbserver_state_t
2526
{
27+
// Offset: 0
2628
uint16_t registers[REGISTERS_COUNT]; /* sp, pc, hl, de, bc, af */
29+
// Offset: 12
2730
uint8_t rst8_handler[80];
31+
// Offset: 92
2832
int server_socket;
33+
// Offset: 94
2934
int client_socket;
35+
// Offset: 96
3036
struct {
3137
uint8_t page;
3238
uint16_t handler;
3339
uint16_t next_address;
3440
uint16_t address;
3541
} trap_handler;
42+
// Offset: 103
43+
uint8_t trap_flags;
44+
// Offsets of these is not important
3645
uint8_t buffer[128];
3746
uint8_t w_buffer[128];
3847
struct breakpoint_t breakpoints[8];
48+
struct breakpoint_t temporary_breakpoint;
3949
};
4050

51+
#define TRAP_FLAG_RESTORE_RST08H (0x01)
52+
#define TRAP_FLAG_STEP_INSTRUCTION (0x02)
53+
4154
extern struct gdbserver_state_t gdbserver_state;
4255

4356
#endif

src/vars.inc

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,3 +12,4 @@ defc gdbserver_register_af = gdbserver_registers + 10
1212
defc gdbserver_rst8_handler = gdbserver_state + 12
1313
defc gdbserver_sockets = gdbserver_rst8_handler + 80
1414
defc gdbserver_trap_handler = gdbserver_sockets + 4
15+
defc gdbserver_trap_flags = gdbserver_trap_handler + 7

0 commit comments

Comments
 (0)