Mercurial > repos > blastem
comparison gdb_remote.c @ 803:236a184bf6f0
Merge
author | Michael Pavone <pavone@retrodev.com> |
---|---|
date | Sun, 26 Jul 2015 16:51:03 -0700 |
parents | 6811f601008f 092524bb2e8f |
children | 59e664fa2da8 |
comparison
equal
deleted
inserted
replaced
802:6811f601008f | 803:236a184bf6f0 |
---|---|
21 #endif | 21 #endif |
22 | 22 |
23 #include "gdb_remote.h" | 23 #include "gdb_remote.h" |
24 #include "68kinst.h" | 24 #include "68kinst.h" |
25 #include "debug.h" | 25 #include "debug.h" |
26 #include "util.h" | |
26 #include <unistd.h> | 27 #include <unistd.h> |
27 #include <fcntl.h> | 28 #include <fcntl.h> |
28 #include <stddef.h> | 29 #include <stddef.h> |
29 #include <stdlib.h> | 30 #include <stdlib.h> |
30 #include <stdio.h> | 31 #include <stdio.h> |
93 } | 94 } |
94 | 95 |
95 void write_or_die(int fd, const void *buf, size_t count) | 96 void write_or_die(int fd, const void *buf, size_t count) |
96 { | 97 { |
97 if (GDB_WRITE(fd, buf, count) < count) { | 98 if (GDB_WRITE(fd, buf, count) < count) { |
98 fputs("Error writing to stdout\n", stderr); | 99 fatal_error("Error writing to stdout\n"); |
99 exit(1); | |
100 } | 100 } |
101 } | 101 } |
102 | 102 |
103 void gdb_send_command(char * command) | 103 void gdb_send_command(char * command) |
104 { | 104 { |
132 } | 132 } |
133 } | 133 } |
134 | 134 |
135 uint8_t read_byte(m68k_context * context, uint32_t address) | 135 uint8_t read_byte(m68k_context * context, uint32_t address) |
136 { | 136 { |
137 uint16_t * word; | 137 |
138 //TODO: Use generated read/write functions so that memory map is properly respected | 138 genesis_context *gen = context->system; |
139 if (address < 0x400000) { | 139 //TODO: Use generated read/write functions to support access to hardware that is not ROM or RAM |
140 word = context->mem_pointers[0] + address/2; | 140 uint16_t * word = get_native_pointer(address & 0xFFFFFFFE, (void **)context->mem_pointers, &context->options->gen); |
141 } else if (address >= 0xE00000) { | 141 if (word) { |
142 word = context->mem_pointers[1] + (address & 0xFFFF)/2; | |
143 } else if (address >= 0xA00000 && address < 0xA04000) { | |
144 return z80_ram[address & 0x1FFF]; | |
145 } else { | |
146 return 0; | |
147 } | |
148 if (address & 1) { | 142 if (address & 1) { |
149 return *word; | 143 return *word; |
150 } | 144 } |
151 return *word >> 8; | 145 return *word >> 8; |
152 } | 146 } |
147 if (address >= 0xA00000 && address < 0xA04000) { | |
148 return gen->zram[address & 0x1FFF]; | |
149 } | |
150 return 0; | |
151 } | |
153 | 152 |
154 void write_byte(m68k_context * context, uint32_t address, uint8_t value) | 153 void write_byte(m68k_context * context, uint32_t address, uint8_t value) |
155 { | 154 { |
156 uint16_t * word; | 155 genesis_context *gen = context->system; |
157 //TODO: Use generated read/write functions so that memory map is properly respected | 156 //TODO: Use generated read/write functions so that memory map is properly respected |
158 if (address < 0x400000) { | 157 uint16_t * word = get_native_pointer(address & 0xFFFFFFFE, (void **)context->mem_pointers, &context->options->gen); |
159 //TODO: Invalidate translated code | 158 if (word) { |
160 word = context->mem_pointers[0] + address/2; | 159 if (address & 1) { |
161 } else if (address >= 0xE00000) { | 160 *word = (*word & 0xFF00) | value; |
162 m68k_handle_code_write(address & 0xFFFF, context); | 161 } else { |
163 word = context->mem_pointers[1] + (address & 0xFFFF)/2; | 162 *word = (*word & 0xFF) | value << 8; |
164 } else if (address >= 0xA00000 && address < 0xA04000) { | 163 } |
164 //TODO: Deal with this more generally once m68k_handle_code_write can handle it | |
165 if (address >= 0xE00000) { | |
166 m68k_handle_code_write(address, context); | |
167 } | |
168 return; | |
169 } | |
170 if (address >= 0xA00000 && address < 0xA04000) { | |
165 z80_ram[address & 0x1FFF] = value; | 171 z80_ram[address & 0x1FFF] = value; |
166 genesis_context * gen = context->system; | 172 genesis_context * gen = context->system; |
167 #ifndef NO_Z80 | 173 #ifndef NO_Z80 |
168 z80_handle_code_GDB_WRITE(address & 0x1FFF, gen->z80); | 174 z80_handle_code_GDB_WRITE(address & 0x1FFF, gen->z80); |
169 #endif | 175 #endif |
170 return; | 176 return; |
171 } else { | 177 } else { |
172 return; | 178 return; |
173 } | 179 } |
174 if (address & 1) { | |
175 *word = (*word & 0xFF00) | value; | |
176 } else { | |
177 *word = (*word & 0xFF) | value << 8; | |
178 } | |
179 } | 180 } |
180 | 181 |
181 void gdb_run_command(m68k_context * context, uint32_t pc, char * command) | 182 void gdb_run_command(m68k_context * context, uint32_t pc, char * command) |
182 { | 183 { |
183 char send_buf[512]; | 184 char send_buf[512]; |
197 if (*(command+1) != 0) { | 198 if (*(command+1) != 0) { |
198 //TODO: implement resuming at an arbitrary address | 199 //TODO: implement resuming at an arbitrary address |
199 goto not_impl; | 200 goto not_impl; |
200 } | 201 } |
201 m68kinst inst; | 202 m68kinst inst; |
202 uint16_t * pc_ptr; | 203 genesis_context *gen = context->system; |
203 if (pc < 0x400000) { | 204 uint16_t * pc_ptr = get_native_pointer(pc, (void **)context->mem_pointers, &context->options->gen); |
204 pc_ptr = cart + pc/2; | 205 if (!pc_ptr) { |
205 } else if(pc > 0xE00000) { | 206 fatal_error("Entered gdb remote debugger stub at address %X\n", pc); |
206 pc_ptr = ram + (pc & 0xFFFF)/2; | |
207 } else { | |
208 fprintf(stderr, "Entered gdb remote debugger stub at address %X\n", pc); | |
209 exit(1); | |
210 } | 207 } |
211 uint16_t * after_pc = m68k_decode(pc_ptr, &inst, pc & 0xFFFFFF); | 208 uint16_t * after_pc = m68k_decode(pc_ptr, &inst, pc & 0xFFFFFF); |
212 uint32_t after = pc + (after_pc-pc_ptr)*2; | 209 uint32_t after = pc + (after_pc-pc_ptr)*2; |
213 | 210 |
214 if (inst.op == M68K_RTS) { | 211 if (inst.op == M68K_RTS) { |
300 } | 297 } |
301 case 'm': { | 298 case 'm': { |
302 char * rest; | 299 char * rest; |
303 uint32_t address = strtoul(command+1, &rest, 16); | 300 uint32_t address = strtoul(command+1, &rest, 16); |
304 uint32_t size = strtoul(rest+1, NULL, 16); | 301 uint32_t size = strtoul(rest+1, NULL, 16); |
305 if (size > sizeof(send_buf-1)/2) { | 302 if (size > (sizeof(send_buf)-1)/2) { |
306 size = sizeof(send_buf-1)/2; | 303 size = (sizeof(send_buf)-1)/2; |
307 } | 304 } |
308 char *cur = send_buf; | 305 char *cur = send_buf; |
309 while (size) | 306 while (size) |
310 { | 307 { |
311 hex_8(read_byte(context, address), cur); | 308 hex_8(read_byte(context, address), cur); |
418 expect_break_response = 1; | 415 expect_break_response = 1; |
419 break; | 416 break; |
420 case 's': | 417 case 's': |
421 case 'S': { | 418 case 'S': { |
422 m68kinst inst; | 419 m68kinst inst; |
423 uint16_t * pc_ptr; | 420 genesis_context *gen = context->system; |
424 if (pc < 0x400000) { | 421 uint16_t * pc_ptr = get_native_pointer(pc, (void **)context->mem_pointers, &context->options->gen); |
425 pc_ptr = cart + pc/2; | 422 if (!pc_ptr) { |
426 } else if(pc > 0xE00000) { | 423 fatal_error("Entered gdb remote debugger stub at address %X\n", pc); |
427 pc_ptr = ram + (pc & 0xFFFF)/2; | |
428 } else { | |
429 fprintf(stderr, "Entered gdb remote debugger stub at address %X\n", pc); | |
430 exit(1); | |
431 } | 424 } |
432 uint16_t * after_pc = m68k_decode(pc_ptr, &inst, pc & 0xFFFFFF); | 425 uint16_t * after_pc = m68k_decode(pc_ptr, &inst, pc & 0xFFFFFF); |
433 uint32_t after = pc + (after_pc-pc_ptr)*2; | 426 uint32_t after = pc + (after_pc-pc_ptr)*2; |
434 | 427 |
435 if (inst.op == M68K_RTS) { | 428 if (inst.op == M68K_RTS) { |
469 goto not_impl; | 462 goto not_impl; |
470 | 463 |
471 } | 464 } |
472 return; | 465 return; |
473 not_impl: | 466 not_impl: |
474 fprintf(stderr, "Command %s is not implemented, exiting...\n", command); | 467 fatal_error("Command %s is not implemented, exiting...\n", command); |
475 exit(1); | |
476 } | 468 } |
477 | 469 |
478 m68k_context * gdb_debug_enter(m68k_context * context, uint32_t pc) | 470 m68k_context * gdb_debug_enter(m68k_context * context, uint32_t pc) |
479 { | 471 { |
480 dfprintf(stderr, "Entered debugger at address %X\n", pc); | 472 dfprintf(stderr, "Entered debugger at address %X\n", pc); |
538 //TODO: verify checksum | 530 //TODO: verify checksum |
539 //Null terminate payload | 531 //Null terminate payload |
540 *curbuf = 0; | 532 *curbuf = 0; |
541 //send acknowledgement | 533 //send acknowledgement |
542 if (GDB_WRITE(GDB_OUT_FD, "+", 1) < 1) { | 534 if (GDB_WRITE(GDB_OUT_FD, "+", 1) < 1) { |
543 fputs("Error writing to stdout\n", stderr); | 535 fatal_error("Error writing to stdout\n"); |
544 exit(1); | |
545 } | 536 } |
546 gdb_run_command(context, pc, start); | 537 gdb_run_command(context, pc, start); |
547 curbuf += 2; | 538 curbuf += 2; |
548 } | 539 } |
549 } else { | 540 } else { |