Commit | Line | Data |
---|---|---|
1f46923f | 1 | /* Remote debugging interface for Hitachi HMS Monitor Version 1.0 |
5d747d61 | 2 | Copyright 1995 Free Software Foundation, Inc. |
e17960fb JG |
3 | Contributed by Cygnus Support. Written by Steve Chamberlain |
4 | (sac@cygnus.com). | |
fa4b55a1 | 5 | |
03fc5a0b | 6 | This file is part of GDB. |
fa4b55a1 | 7 | |
03fc5a0b SC |
8 | This program is free software; you can redistribute it and/or modify |
9 | it under the terms of the GNU General Public License as published by | |
10 | the Free Software Foundation; either version 2 of the License, or | |
11 | (at your option) any later version. | |
fa4b55a1 | 12 | |
03fc5a0b SC |
13 | This program is distributed in the hope that it will be useful, |
14 | but WITHOUT ANY WARRANTY; without even the implied warranty of | |
15 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
16 | GNU General Public License for more details. | |
fa4b55a1 | 17 | |
03fc5a0b SC |
18 | You should have received a copy of the GNU General Public License |
19 | along with this program; if not, write to the Free Software | |
20 | Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ | |
fa4b55a1 | 21 | |
fa4b55a1 | 22 | #include "defs.h" |
5d747d61 SC |
23 | #include "gdbcore.h" |
24 | #include "target.h" | |
25 | #include "monitor.h" | |
26 | #include "serial.h" | |
27 | ||
28 | static void hms_open PARAMS ((char *args, int from_tty)); | |
29 | ||
30 | static void | |
31 | hms_supply_register (regname, regnamelen, val, vallen) | |
32 | char *regname; | |
33 | int regnamelen; | |
34 | char *val; | |
35 | int vallen; | |
36 | { | |
37 | int regno; | |
38 | ||
39 | if (regnamelen != 2) | |
40 | return; | |
41 | if (regname[0] != 'P') | |
42 | return; | |
43 | /* We scan off all the registers in one go */ | |
44 | ||
45 | val = monitor_supply_register (PC_REGNUM, val); | |
46 | /* Skip the ccr string */ | |
47 | while (*val != '=' && *val) | |
48 | val++; | |
49 | ||
50 | val = monitor_supply_register (CCR_REGNUM, val + 1); | |
51 | ||
52 | /* Skip up to rest of regs */ | |
53 | while (*val != '=' && *val) | |
54 | val++; | |
55 | ||
56 | for (regno = 0; regno < 7; regno++) | |
57 | { | |
58 | val = monitor_supply_register (regno, val + 1); | |
59 | } | |
60 | } | |
61 | ||
62 | /* | |
63 | * This array of registers needs to match the indexes used by GDB. The | |
64 | * whole reason this exists is because the various ROM monitors use | |
65 | * different names than GDB does, and don't support all the | |
66 | * registers either. So, typing "info reg sp" becomes a "r30". | |
67 | */ | |
68 | ||
69 | static char *hms_regnames[NUM_REGS] = | |
70 | { | |
71 | "R0", "R1", "R2", "R3", "R4", "R5", "R6", "R7", "CCR", "PC" | |
72 | }; | |
73 | ||
74 | /* | |
75 | * Define the monitor command strings. Since these are passed directly | |
76 | * through to a printf style function, we need can include formatting | |
77 | * strings. We also need a CR or LF on the end. | |
78 | */ | |
79 | ||
80 | static struct target_ops hms_ops; | |
81 | ||
82 | static char *hms_inits[] = | |
83 | {"\003", /* Resets the prompt, and clears repeated cmds */ | |
84 | NULL}; | |
85 | ||
86 | static struct monitor_ops hms_cmds = | |
87 | { | |
88 | MO_CLR_BREAK_USES_ADDR | MO_FILL_USES_ADDR | MO_GETMEM_NEEDS_RANGE, | |
89 | hms_inits, /* Init strings */ | |
90 | "g\r", /* continue command */ | |
91 | "s\r", /* single step */ | |
92 | "\003", /* ^C interrupts the program */ | |
93 | "b %x\r", /* set a breakpoint */ | |
94 | "b - %x\r", /* clear a breakpoint */ | |
95 | "b -\r", /* clear all breakpoints */ | |
96 | "f %x %x %x\r", /* fill (start end val) */ | |
97 | { | |
98 | "m.b %x=%x\r", /* setmem.cmdb (addr, value) */ | |
99 | "m.w %x=%x\r", /* setmem.cmdw (addr, value) */ | |
100 | NULL, /* setmem.cmdl (addr, value) */ | |
101 | NULL, /* setmem.cmdll (addr, value) */ | |
102 | NULL, /* setreg.resp_delim */ | |
103 | NULL, /* setreg.term */ | |
104 | NULL, /* setreg.term_cmd */ | |
105 | }, | |
106 | { | |
107 | "m.b %x %x\r", /* getmem.cmdb (addr, addr) */ | |
108 | "m.w %x %x\r", /* getmem.cmdw (addr, addr) */ | |
109 | NULL, /* getmem.cmdl (addr, addr) */ | |
110 | NULL, /* getmem.cmdll (addr, addr) */ | |
111 | ": ", /* getmem.resp_delim */ | |
112 | ">", /* getmem.term */ | |
113 | "\003", /* getmem.term_cmd */ | |
114 | }, | |
115 | { | |
116 | "\003r %s=%x\r", /* setreg.cmd (name, value) */ | |
117 | NULL, /* setreg.resp_delim */ | |
118 | NULL, /* setreg.term */ | |
119 | NULL /* setreg.term_cmd */ | |
120 | }, | |
121 | { | |
122 | "r %s\r", /* getreg.cmd (name) */ | |
123 | " (", /* getreg.resp_delim */ | |
124 | "):", /* getreg.term */ | |
125 | "\003", /* getreg.term_cmd */ | |
126 | }, | |
127 | "r\r", /* dump_registers */ | |
128 | "\\(\\w+\\)=\\([0-9a-fA-F]+\\)", /* register_pattern */ | |
129 | hms_supply_register, /* supply_register */ | |
130 | NULL, /* load_routine (defaults to SRECs) */ | |
131 | "tl\r", /* download command */ | |
132 | NULL, /* load response */ | |
133 | ">", /* monitor command prompt */ | |
134 | NULL, /* end-of-command delimitor */ | |
135 | NULL, /* optional command terminator */ | |
136 | &hms_ops, /* target operations */ | |
137 | SERIAL_1_STOPBITS, /* number of stop bits */ | |
138 | hms_regnames, /* registers names */ | |
139 | MONITOR_OPS_MAGIC /* magic */ | |
140 | }; | |
141 | ||
142 | void | |
143 | hms_open (args, from_tty) | |
144 | char *args; | |
145 | int from_tty; | |
146 | { | |
147 | monitor_open (args, &hms_cmds, from_tty); | |
148 | } | |
149 | ||
150 | ||
151 | int write_dos_tick_delay; | |
152 | void | |
153 | _initialize_remote_hms () | |
154 | { | |
155 | init_monitor_ops (&hms_ops); | |
156 | ||
157 | hms_ops.to_shortname = "hms"; | |
158 | hms_ops.to_longname = "Hitachi Microsystems H8/300 debug monitor"; | |
159 | hms_ops.to_doc = "Debug via the HMS monitor.\n\ | |
160 | Specify the serial device it is connected to (e.g. /dev/ttya)."; | |
161 | hms_ops.to_open = hms_open; | |
162 | /* By trial and error I've found that this delay doesn't break things */ | |
163 | write_dos_tick_delay = 1; | |
164 | add_target (&hms_ops); | |
165 | } | |
166 | ||
167 | ||
168 | ||
169 | #if 0 | |
170 | /* This is kept here because we used to support the H8/500 in this module, | |
171 | and I haven't done the H8/500 yet */ | |
172 | #include "defs.h" | |
fa4b55a1 SC |
173 | #include "inferior.h" |
174 | #include "wait.h" | |
175 | #include "value.h" | |
e17960fb | 176 | #include <string.h> |
fa4b55a1 SC |
177 | #include <ctype.h> |
178 | #include <fcntl.h> | |
179 | #include <signal.h> | |
180 | #include <setjmp.h> | |
181 | #include <errno.h> | |
182 | #include "terminal.h" | |
183 | #include "target.h" | |
184 | #include "gdbcore.h" | |
a493d9a6 | 185 | #include "serial.h" |
03fc5a0b | 186 | #include "remote-utils.h" |
fa4b55a1 | 187 | /* External data declarations */ |
ec25d19b | 188 | extern int stop_soon_quietly; /* for wait_for_inferior */ |
fa4b55a1 | 189 | |
fa4b55a1 | 190 | /* Forward data declarations */ |
ec25d19b | 191 | extern struct target_ops hms_ops; /* Forward declaration */ |
fa4b55a1 SC |
192 | |
193 | /* Forward function declarations */ | |
194 | static void hms_fetch_registers (); | |
ec25d19b | 195 | static int hms_store_registers (); |
fa4b55a1 | 196 | static void hms_close (); |
ec25d19b | 197 | static int hms_clear_breakpoints (); |
fa4b55a1 SC |
198 | |
199 | extern struct target_ops hms_ops; | |
3b5442f9 SC |
200 | static void hms_drain (); |
201 | static void add_commands (); | |
202 | static void remove_commands (); | |
fa4b55a1 | 203 | |
03fc5a0b | 204 | static int quiet = 1; /* FIXME - can be removed after Dec '94 */ |
a493d9a6 | 205 | |
5d747d61 SC |
206 | DCACHE *dcache_ptr; |
207 | int remote_dcache; | |
a493d9a6 SC |
208 | serial_t desc; |
209 | ||
fa4b55a1 | 210 | |
1f46923f SC |
211 | /*********************************************************************** |
212 | * I/O stuff stolen from remote-eb.c | |
213 | ***********************************************************************/ | |
214 | ||
215 | static int timeout = 2; | |
fa4b55a1 | 216 | |
b52373a2 | 217 | static const char *dev_name; |
1f46923f | 218 | |
fa4b55a1 SC |
219 | /* Descriptor for I/O to remote machine. Initialize it to -1 so that |
220 | hms_open knows that we don't have a file open when the program | |
221 | starts. */ | |
fa4b55a1 | 222 | |
402b0d2e SC |
223 | static int before = 0xdead; |
224 | static int is_open = 0; | |
225 | static int after = 0xdead; | |
a493d9a6 | 226 | int |
ec25d19b | 227 | check_open () |
fa4b55a1 | 228 | { |
03fc5a0b SC |
229 | if (before != 0xdead |
230 | || after != 0xdead) | |
231 | printf ("OUTCH! \n"); | |
ae0ea72e | 232 | if (!is_open) |
ec25d19b SC |
233 | { |
234 | error ("remote device not open"); | |
235 | } | |
fa4b55a1 SC |
236 | } |
237 | ||
ae0ea72e SC |
238 | #define ON 1 |
239 | #define OFF 0 | |
1f46923f SC |
240 | |
241 | /* Read a character from the remote system, doing all the fancy | |
242 | timeout stuff. */ | |
243 | static int | |
244 | readchar () | |
fa4b55a1 | 245 | { |
ae0ea72e | 246 | int buf; |
ec25d19b | 247 | |
a493d9a6 | 248 | buf = SERIAL_READCHAR (desc, timeout); |
1f46923f | 249 | |
a493d9a6 | 250 | if (buf == SERIAL_TIMEOUT) |
3b5442f9 SC |
251 | { |
252 | hms_write (".\r\n", 3); | |
253 | error ("Timeout reading from remote system."); | |
254 | } | |
255 | if (buf == SERIAL_ERROR) | |
256 | { | |
257 | error ("Serial port error!"); | |
258 | } | |
1f46923f | 259 | |
791d4d7d | 260 | if (!quiet || remote_debug) |
199b2450 | 261 | printf_unfiltered ("%c", buf); |
ec25d19b | 262 | |
1f46923f | 263 | return buf & 0x7f; |
fa4b55a1 SC |
264 | } |
265 | ||
5d747d61 | 266 | static void |
03fc5a0b | 267 | flush () |
402b0d2e SC |
268 | { |
269 | while (1) | |
270 | { | |
271 | int b = SERIAL_READCHAR (desc, 0); | |
272 | if (b == SERIAL_TIMEOUT) | |
273 | return; | |
274 | } | |
275 | } | |
276 | ||
fa4b55a1 | 277 | static int |
1f46923f | 278 | readchar_nofail () |
fa4b55a1 | 279 | { |
ae0ea72e | 280 | int buf; |
ec25d19b | 281 | |
a493d9a6 SC |
282 | buf = SERIAL_READCHAR (desc, timeout); |
283 | if (buf == SERIAL_TIMEOUT) | |
ec25d19b | 284 | buf = 0; |
791d4d7d | 285 | if (!quiet || remote_debug) |
199b2450 | 286 | printf_unfiltered ("%c", buf); |
ec25d19b | 287 | |
fa4b55a1 | 288 | return buf & 0x7f; |
ae0ea72e | 289 | |
fa4b55a1 SC |
290 | } |
291 | ||
ec25d19b | 292 | /* Keep discarding input from the remote system, until STRING is found. |
fa4b55a1 SC |
293 | Let the user break out immediately. */ |
294 | static void | |
295 | expect (string) | |
296 | char *string; | |
297 | { | |
298 | char *p = string; | |
402b0d2e | 299 | char c; |
fa4b55a1 SC |
300 | immediate_quit = 1; |
301 | while (1) | |
302 | { | |
03fc5a0b | 303 | c = readchar (); |
402b0d2e | 304 | if (c == *p) |
fa4b55a1 SC |
305 | { |
306 | p++; | |
307 | if (*p == '\0') | |
308 | { | |
309 | immediate_quit = 0; | |
310 | return; | |
311 | } | |
312 | } | |
03fc5a0b | 313 | else |
402b0d2e SC |
314 | { |
315 | p = string; | |
316 | if (c == *p) | |
317 | p++; | |
318 | } | |
fa4b55a1 SC |
319 | } |
320 | } | |
321 | ||
322 | /* Keep discarding input until we see the hms prompt. | |
323 | ||
324 | The convention for dealing with the prompt is that you | |
325 | o give your command | |
326 | o *then* wait for the prompt. | |
327 | ||
328 | Thus the last thing that a procedure does with the serial line | |
329 | will be an expect_prompt(). Exception: hms_resume does not | |
330 | wait for the prompt, because the terminal is being handed over | |
331 | to the inferior. However, the next thing which happens after that | |
332 | is a hms_wait which does wait for the prompt. | |
333 | Note that this includes abnormal exit, e.g. error(). This is | |
334 | necessary to prevent getting into states from which we can't | |
335 | recover. */ | |
336 | static void | |
337 | expect_prompt () | |
338 | { | |
fa4b55a1 SC |
339 | expect ("HMS>"); |
340 | } | |
341 | ||
342 | /* Get a hex digit from the remote system & return its value. | |
343 | If ignore_space is nonzero, ignore spaces (not newline, tab, etc). */ | |
344 | static int | |
345 | get_hex_digit (ignore_space) | |
346 | int ignore_space; | |
347 | { | |
348 | int ch; | |
ec25d19b | 349 | |
fa4b55a1 SC |
350 | while (1) |
351 | { | |
352 | ch = readchar (); | |
353 | if (ch >= '0' && ch <= '9') | |
354 | return ch - '0'; | |
355 | else if (ch >= 'A' && ch <= 'F') | |
356 | return ch - 'A' + 10; | |
357 | else if (ch >= 'a' && ch <= 'f') | |
358 | return ch - 'a' + 10; | |
359 | else if (ch == ' ' && ignore_space) | |
360 | ; | |
361 | else | |
362 | { | |
363 | expect_prompt (); | |
364 | error ("Invalid hex digit from remote system."); | |
365 | } | |
366 | } | |
367 | } | |
368 | ||
369 | /* Get a byte from hms_desc and put it in *BYT. Accept any number | |
370 | leading spaces. */ | |
371 | static void | |
372 | get_hex_byte (byt) | |
373 | char *byt; | |
374 | { | |
375 | int val; | |
376 | ||
377 | val = get_hex_digit (1) << 4; | |
378 | val |= get_hex_digit (0); | |
379 | *byt = val; | |
380 | } | |
381 | ||
382 | /* Read a 32-bit hex word from the hms, preceded by a space */ | |
ec25d19b SC |
383 | static long |
384 | get_hex_word () | |
fa4b55a1 SC |
385 | { |
386 | long val; | |
387 | int j; | |
ec25d19b | 388 | |
fa4b55a1 SC |
389 | val = 0; |
390 | for (j = 0; j < 8; j++) | |
ec25d19b | 391 | val = (val << 4) + get_hex_digit (j == 0); |
fa4b55a1 SC |
392 | return val; |
393 | } | |
fa4b55a1 | 394 | |
ec25d19b | 395 | /* Called when SIGALRM signal sent due to alarm() timeout. */ |
fa4b55a1 SC |
396 | |
397 | /* Number of SIGTRAPs we need to simulate. That is, the next | |
398 | NEED_ARTIFICIAL_TRAP calls to hms_wait should just return | |
399 | SIGTRAP without actually waiting for anything. */ | |
400 | ||
401 | static int need_artificial_trap = 0; | |
402 | ||
403 | void | |
ec25d19b SC |
404 | hms_kill (arg, from_tty) |
405 | char *arg; | |
406 | int from_tty; | |
fa4b55a1 | 407 | { |
fa4b55a1 | 408 | |
fa4b55a1 | 409 | } |
1f46923f | 410 | |
fa4b55a1 SC |
411 | /* This is called not only when we first attach, but also when the |
412 | user types "run" after having attached. */ | |
413 | void | |
414 | hms_create_inferior (execfile, args, env) | |
415 | char *execfile; | |
416 | char *args; | |
417 | char **env; | |
418 | { | |
419 | int entry_pt; | |
ec25d19b | 420 | char buffer[100]; |
fa4b55a1 SC |
421 | |
422 | if (args && *args) | |
ec25d19b | 423 | error ("Can't pass arguments to remote hms process."); |
fa4b55a1 SC |
424 | |
425 | if (execfile == 0 || exec_bfd == 0) | |
ec25d19b | 426 | error ("No exec file specified"); |
fa4b55a1 SC |
427 | |
428 | entry_pt = (int) bfd_get_start_address (exec_bfd); | |
ec25d19b | 429 | check_open (); |
1f46923f | 430 | |
ec25d19b SC |
431 | hms_kill (NULL, NULL); |
432 | hms_clear_breakpoints (); | |
ae0ea72e | 433 | init_wait_for_inferior (); |
ec25d19b SC |
434 | hms_write_cr (""); |
435 | expect_prompt (); | |
fa4b55a1 | 436 | |
ae0ea72e | 437 | insert_breakpoints (); /* Needed to get correct instruction in cache */ |
45dc9be3 | 438 | proceed (entry_pt, TARGET_SIGNAL_DEFAULT, 0); |
fa4b55a1 SC |
439 | } |
440 | ||
fa4b55a1 SC |
441 | /* Open a connection to a remote debugger. |
442 | NAME is the filename used for communication, then a space, | |
443 | then the baud rate. | |
444 | */ | |
445 | ||
446 | static char * | |
ec25d19b SC |
447 | find_end_of_word (s) |
448 | char *s; | |
fa4b55a1 | 449 | { |
ec25d19b SC |
450 | while (*s && !isspace (*s)) |
451 | s++; | |
fa4b55a1 SC |
452 | return s; |
453 | } | |
454 | ||
ec25d19b SC |
455 | static char * |
456 | get_word (p) | |
457 | char **p; | |
fa4b55a1 SC |
458 | { |
459 | char *s = *p; | |
ec25d19b | 460 | char *word; |
fa4b55a1 SC |
461 | char *copy; |
462 | size_t len; | |
463 | ||
ec25d19b SC |
464 | while (isspace (*s)) |
465 | s++; | |
fa4b55a1 SC |
466 | |
467 | word = s; | |
468 | ||
469 | len = 0; | |
470 | ||
ec25d19b SC |
471 | while (*s && !isspace (*s)) |
472 | { | |
473 | s++; | |
474 | len++; | |
475 | ||
476 | } | |
477 | copy = xmalloc (len + 1); | |
478 | memcpy (copy, word, len); | |
fa4b55a1 SC |
479 | copy[len] = 0; |
480 | *p = s; | |
481 | return copy; | |
482 | } | |
483 | ||
484 | static int baudrate = 9600; | |
1f46923f SC |
485 | |
486 | static int | |
ec25d19b | 487 | is_baudrate_right () |
1f46923f | 488 | { |
ae0ea72e | 489 | int ok; |
ec25d19b | 490 | |
1f46923f | 491 | /* Put this port into NORMAL mode, send the 'normal' character */ |
ae0ea72e | 492 | |
ec25d19b | 493 | hms_write ("\001", 1); /* Control A */ |
3b5442f9 | 494 | hms_write ("\r\n", 2); /* Cr */ |
ae0ea72e | 495 | |
ec25d19b SC |
496 | while (1) |
497 | { | |
a493d9a6 | 498 | ok = SERIAL_READCHAR (desc, timeout); |
ec25d19b SC |
499 | if (ok < 0) |
500 | break; | |
501 | } | |
ae0ea72e | 502 | |
ec25d19b SC |
503 | hms_write ("r", 1); |
504 | ||
505 | if (readchar_nofail () == 'r') | |
506 | return 1; | |
1f46923f SC |
507 | |
508 | /* Not the right baudrate, or the board's not on */ | |
509 | return 0; | |
1f46923f SC |
510 | } |
511 | static void | |
ec25d19b | 512 | set_rate () |
1f46923f | 513 | { |
a493d9a6 | 514 | if (!SERIAL_SETBAUDRATE (desc, baudrate)) |
ec25d19b | 515 | error ("Can't set baudrate"); |
1f46923f SC |
516 | } |
517 | ||
1f46923f | 518 | |
fa4b55a1 SC |
519 | |
520 | /* Close out all files and local state before this target loses control. */ | |
521 | ||
522 | static void | |
523 | hms_close (quitting) | |
524 | int quitting; | |
525 | { | |
fa4b55a1 | 526 | /* Clear any break points */ |
3b5442f9 | 527 | remove_commands (); |
ec25d19b | 528 | hms_clear_breakpoints (); |
ec25d19b | 529 | sleep (1); /* Let any output make it all the way back */ |
a493d9a6 SC |
530 | if (is_open) |
531 | { | |
3b5442f9 | 532 | SERIAL_WRITE (desc, "R\r\n", 3); |
a493d9a6 SC |
533 | SERIAL_CLOSE (desc); |
534 | } | |
ae0ea72e | 535 | is_open = 0; |
5d747d61 | 536 | remote_dcache = 0; |
fa4b55a1 SC |
537 | } |
538 | ||
3b5442f9 | 539 | /* Terminate the open connection to the remote debugger. Use this |
03fc5a0b | 540 | when you want to detach and do something else with your gdb. */ void |
ec25d19b | 541 | hms_detach (args, from_tty) |
fa4b55a1 SC |
542 | char *args; |
543 | int from_tty; | |
544 | { | |
ae0ea72e | 545 | if (is_open) |
ec25d19b SC |
546 | { |
547 | hms_clear_breakpoints (); | |
548 | } | |
549 | ||
3b5442f9 | 550 | pop_target (); /* calls hms_close to do the real work |
03fc5a0b | 551 | */ |
fa4b55a1 | 552 | if (from_tty) |
3b5442f9 SC |
553 | printf_filtered ("Ending remote %s debugging\n", |
554 | target_shortname); | |
fa4b55a1 | 555 | } |
ec25d19b | 556 | |
fa4b55a1 SC |
557 | /* Tell the remote machine to resume. */ |
558 | ||
559 | void | |
25286543 | 560 | hms_resume (pid, step, sig) |
67ac9759 | 561 | int pid, step; |
3b5442f9 SC |
562 | enum target_signal |
563 | sig; | |
fa4b55a1 | 564 | { |
5d747d61 | 565 | dcache_flush (dcache_ptr); |
ec25d19b SC |
566 | |
567 | if (step) | |
568 | { | |
569 | hms_write_cr ("s"); | |
570 | expect ("Step>"); | |
571 | ||
572 | /* Force the next hms_wait to return a trap. Not doing anything | |
03fc5a0b SC |
573 | about I/O from the target means that the user has to type "continue" |
574 | to see any. FIXME, this should be fixed. */ | |
ec25d19b SC |
575 | need_artificial_trap = 1; |
576 | } | |
fa4b55a1 | 577 | else |
ec25d19b SC |
578 | { |
579 | hms_write_cr ("g"); | |
580 | expect ("g"); | |
581 | } | |
fa4b55a1 SC |
582 | } |
583 | ||
3b5442f9 | 584 | /* Wait until the remote machine stops, then return, storing status in |
03fc5a0b | 585 | STATUS just as `wait' would. */ |
fa4b55a1 SC |
586 | |
587 | int | |
de43d7d0 SG |
588 | hms_wait (pid, status) |
589 | int pid; | |
67ac9759 | 590 | struct target_waitstatus *status; |
fa4b55a1 | 591 | { |
3b5442f9 SC |
592 | /* Strings to look for. '?' means match any single character. Note |
593 | that with the algorithm we use, the initial character of the string | |
594 | cannot recur in the string, or we will not find some cases of the | |
595 | string in the input. */ | |
ec25d19b | 596 | |
96743d3c | 597 | static char bpt[] = "At breakpoint:"; |
ec25d19b | 598 | |
3b5442f9 SC |
599 | /* It would be tempting to look for "\n[__exit + 0x8]\n" but that |
600 | requires loading symbols with "yc i" and even if we did do that we | |
03fc5a0b SC |
601 | don't know that the file has symbols. */ |
602 | static char exitmsg[] = "HMS>"; | |
fa4b55a1 SC |
603 | char *bp = bpt; |
604 | char *ep = exitmsg; | |
605 | ||
3b5442f9 SC |
606 | /* Large enough for either sizeof (bpt) or sizeof (exitmsg) chars. |
607 | */ | |
fa4b55a1 | 608 | char swallowed[50]; |
ec25d19b | 609 | |
fa4b55a1 SC |
610 | /* Current position in swallowed. */ |
611 | char *swallowed_p = swallowed; | |
612 | ||
613 | int ch; | |
614 | int ch_handled; | |
615 | int old_timeout = timeout; | |
3b5442f9 SC |
616 | int |
617 | old_immediate_quit = immediate_quit; | |
1f46923f | 618 | int swallowed_cr = 0; |
ec25d19b | 619 | |
67ac9759 JK |
620 | status->kind = TARGET_WAITKIND_EXITED; |
621 | status->value.integer = 0; | |
fa4b55a1 SC |
622 | |
623 | if (need_artificial_trap != 0) | |
ec25d19b | 624 | { |
3b5442f9 SC |
625 | status->kind = |
626 | TARGET_WAITKIND_STOPPED; | |
67ac9759 | 627 | status->value.sig = TARGET_SIGNAL_TRAP; |
ec25d19b SC |
628 | need_artificial_trap--; |
629 | return 0; | |
630 | } | |
fa4b55a1 | 631 | |
63eef03a | 632 | timeout = 5; /* Don't time out for a while - user program is running. |
3b5442f9 | 633 | */ |
1f46923f | 634 | immediate_quit = 1; /* Helps ability to QUIT */ |
ec25d19b | 635 | while (1) |
96743d3c | 636 | { |
ec25d19b SC |
637 | QUIT; /* Let user quit and leave process running */ |
638 | ch_handled = 0; | |
639 | ch = readchar (); | |
640 | if (ch == *bp) | |
641 | { | |
642 | bp++; | |
643 | if (*bp == '\0') | |
644 | break; | |
645 | ch_handled = 1; | |
646 | ||
647 | *swallowed_p++ = ch; | |
648 | } | |
649 | else | |
650 | { | |
651 | bp = bpt; | |
652 | } | |
3b5442f9 SC |
653 | if |
654 | (ch == *ep || *ep == '?') | |
03fc5a0b SC |
655 | { |
656 | ep++; | |
657 | if (*ep == '\0') | |
658 | break; | |
659 | ||
660 | if (!ch_handled) | |
661 | *swallowed_p++ = ch; | |
662 | ch_handled = | |
663 | 1; | |
664 | } | |
ec25d19b SC |
665 | else |
666 | { | |
667 | ep = exitmsg; | |
668 | } | |
669 | ||
670 | if (!ch_handled) | |
671 | { | |
672 | char *p; | |
673 | ||
674 | /* Print out any characters which have been swallowed. */ | |
675 | for (p = swallowed; p < swallowed_p; ++p) | |
7baea946 | 676 | putchar_unfiltered (*p); |
ec25d19b SC |
677 | swallowed_p = swallowed; |
678 | ||
679 | if ((ch != '\r' && ch != '\n') || swallowed_cr > 10) | |
680 | { | |
7baea946 | 681 | putchar_unfiltered (ch); |
ec25d19b SC |
682 | swallowed_cr = 10; |
683 | } | |
684 | swallowed_cr++; | |
685 | ||
686 | } | |
96743d3c | 687 | } |
ec25d19b | 688 | if (*bp == '\0') |
96743d3c | 689 | { |
67ac9759 JK |
690 | status->kind = TARGET_WAITKIND_STOPPED; |
691 | status->value.sig = TARGET_SIGNAL_TRAP; | |
ec25d19b SC |
692 | expect_prompt (); |
693 | } | |
694 | else | |
96743d3c | 695 | { |
67ac9759 | 696 | status->kind = TARGET_WAITKIND_EXITED; |
3b5442f9 SC |
697 | status->value.integer = |
698 | TARGET_SIGNAL_STOP; | |
96743d3c | 699 | } |
ec25d19b | 700 | |
fa4b55a1 SC |
701 | timeout = old_timeout; |
702 | immediate_quit = old_immediate_quit; | |
3b5442f9 SC |
703 | return |
704 | 0; | |
fa4b55a1 SC |
705 | } |
706 | ||
3b5442f9 | 707 | /* Return the name of register number REGNO in the form input and |
03fc5a0b | 708 | output by hms. |
fa4b55a1 SC |
709 | |
710 | Returns a pointer to a static buffer containing the answer. */ | |
711 | static char * | |
712 | get_reg_name (regno) | |
713 | int regno; | |
714 | { | |
3b5442f9 SC |
715 | static char *rn[] = |
716 | REGISTER_NAMES; | |
ec25d19b | 717 | |
fa4b55a1 | 718 | return rn[regno]; |
fa4b55a1 SC |
719 | } |
720 | ||
03fc5a0b | 721 | /* Read the remote registers. */ |
3b5442f9 | 722 | |
a493d9a6 | 723 | static int |
ec25d19b SC |
724 | gethex (length, start, ok) |
725 | unsigned int length; | |
726 | char *start; | |
727 | int *ok; | |
fa4b55a1 SC |
728 | { |
729 | int result = 0; | |
ec25d19b SC |
730 | |
731 | while (length--) | |
fa4b55a1 | 732 | { |
ec25d19b SC |
733 | result <<= 4; |
734 | if (*start >= 'a' && *start <= 'f') | |
735 | { | |
736 | result += *start - 'a' + 10; | |
737 | } | |
3b5442f9 SC |
738 | else if (*start >= 'A' && |
739 | *start <= 'F') | |
ec25d19b SC |
740 | { |
741 | result += *start - 'A' + 10; | |
742 | } | |
3b5442f9 SC |
743 | else if |
744 | (*start >= '0' && *start <= '9') | |
03fc5a0b SC |
745 | { |
746 | result += *start - '0'; | |
747 | } | |
ec25d19b SC |
748 | else |
749 | *ok = 0; | |
750 | start++; | |
751 | ||
fa4b55a1 | 752 | } |
fa4b55a1 SC |
753 | return result; |
754 | } | |
ec25d19b SC |
755 | static int |
756 | timed_read (buf, n, timeout) | |
3b5442f9 SC |
757 | char |
758 | *buf; | |
fa4b55a1 SC |
759 | |
760 | { | |
761 | int i; | |
762 | char c; | |
ec25d19b | 763 | |
fa4b55a1 | 764 | i = 0; |
ec25d19b SC |
765 | while (i < n) |
766 | { | |
767 | c = readchar (); | |
768 | ||
769 | if (c == 0) | |
770 | return i; | |
771 | buf[i] = c; | |
772 | i++; | |
773 | ||
774 | } | |
775 | return i; | |
fa4b55a1 | 776 | } |
ec25d19b SC |
777 | |
778 | hms_write (a, l) | |
779 | char *a; | |
fa4b55a1 SC |
780 | { |
781 | int i; | |
ec25d19b | 782 | |
a493d9a6 | 783 | SERIAL_WRITE (desc, a, l); |
ae0ea72e | 784 | |
791d4d7d | 785 | if (!quiet || remote_debug) |
3b5442f9 SC |
786 | { |
787 | printf_unfiltered ("<"); | |
788 | for (i = 0; i < l; i++) | |
789 | { | |
790 | printf_unfiltered ("%c", a[i]); | |
791 | } | |
792 | printf_unfiltered (">"); | |
793 | } | |
fa4b55a1 SC |
794 | } |
795 | ||
ec25d19b SC |
796 | hms_write_cr (s) |
797 | char *s; | |
fa4b55a1 | 798 | { |
ec25d19b | 799 | hms_write (s, strlen (s)); |
3b5442f9 | 800 | hms_write ("\r\n", 2); |
1f46923f SC |
801 | } |
802 | ||
edd01519 SC |
803 | #ifdef GDB_TARGET_IS_H8500 |
804 | ||
805 | /* H8/500 monitor reg dump looks like: | |
806 | ||
03fc5a0b SC |
807 | HMS>r |
808 | PC:8000 SR:070C .7NZ.. CP:00 DP:00 EP:00 TP:00 BR:00 | |
809 | R0-R7: FF5A 0001 F4FE F500 0000 F528 F528 F4EE | |
810 | HMS> | |
edd01519 SC |
811 | |
812 | ||
03fc5a0b | 813 | */ |
edd01519 | 814 | |
3b5442f9 SC |
815 | supply_val (n, size, ptr, segptr) |
816 | int n; | |
817 | int size; | |
818 | char *ptr; | |
819 | char *segptr; | |
edd01519 SC |
820 | { |
821 | int ok; | |
822 | char raw[4]; | |
3b5442f9 | 823 | switch (size) |
edd01519 SC |
824 | { |
825 | case 2: | |
3b5442f9 SC |
826 | raw[0] = gethex (2, ptr, &ok); |
827 | raw[1] = gethex (2, ptr + 2, &ok); | |
edd01519 SC |
828 | supply_register (n, raw); |
829 | break; | |
830 | case 1: | |
3b5442f9 | 831 | raw[0] = gethex (2, ptr, &ok); |
edd01519 SC |
832 | supply_register (n, raw); |
833 | break; | |
834 | case 4: | |
835 | { | |
836 | int v = gethex (4, ptr, &ok); | |
837 | v |= gethex (2, segptr, &ok) << 16; | |
838 | raw[0] = 0; | |
3b5442f9 SC |
839 | raw[1] = (v >> 16) & 0xff; |
840 | raw[2] = (v >> 8) & 0xff; | |
841 | raw[3] = (v >> 0) & 0xff; | |
edd01519 SC |
842 | supply_register (n, raw); |
843 | } | |
844 | } | |
845 | ||
846 | } | |
847 | static void | |
848 | hms_fetch_register (dummy) | |
849 | int dummy; | |
850 | { | |
851 | #define REGREPLY_SIZE 108 | |
852 | char linebuf[REGREPLY_SIZE + 1]; | |
853 | int i; | |
854 | int s; | |
855 | int gottok; | |
856 | ||
678ee700 | 857 | LONGEST reg[NUM_REGS]; |
edd01519 SC |
858 | check_open (); |
859 | ||
860 | do | |
861 | { | |
862 | ||
863 | hms_write_cr ("r"); | |
3b5442f9 SC |
864 | expect ("r"); |
865 | s = timed_read (linebuf + 1, REGREPLY_SIZE, 1); | |
edd01519 SC |
866 | |
867 | linebuf[REGREPLY_SIZE] = 0; | |
868 | gottok = 0; | |
869 | if (linebuf[3] == 'P' && | |
870 | linebuf[4] == 'C' && | |
871 | linebuf[5] == ':' && | |
872 | linebuf[105] == 'H' && | |
873 | linebuf[106] == 'M' && | |
874 | linebuf[107] == 'S') | |
875 | { | |
876 | ||
877 | /* | |
03fc5a0b SC |
878 | 012 |
879 | r** | |
880 | -------1---------2---------3---------4---------5----- | |
881 | 345678901234567890123456789012345678901234567890123456 | |
882 | PC:8000 SR:070C .7NZ.. CP:00 DP:00 EP:00 TP:00 BR:00** | |
883 | ---6---------7---------8---------9--------10---- | |
884 | 789012345678901234567890123456789012345678901234 | |
885 | R0-R7: FF5A 0001 F4FE F500 0000 F528 F528 F4EE** | |
886 | ||
887 | 56789 | |
888 | HMS> | |
889 | */ | |
edd01519 SC |
890 | gottok = 1; |
891 | ||
edd01519 | 892 | |
3b5442f9 SC |
893 | supply_val (PC_REGNUM, 4, linebuf + 6, linebuf + 29); |
894 | ||
895 | supply_val (CCR_REGNUM, 2, linebuf + 14); | |
896 | supply_val (SEG_C_REGNUM, 1, linebuf + 29); | |
897 | supply_val (SEG_D_REGNUM, 1, linebuf + 35); | |
898 | supply_val (SEG_E_REGNUM, 1, linebuf + 41); | |
899 | supply_val (SEG_T_REGNUM, 1, linebuf + 47); | |
edd01519 SC |
900 | for (i = 0; i < 8; i++) |
901 | { | |
3b5442f9 SC |
902 | static int sr[8] = |
903 | {35, 35, 35, 35, | |
904 | 41, 41, 47, 47}; | |
edd01519 SC |
905 | |
906 | char raw[4]; | |
907 | char *src = linebuf + 64 + 5 * i; | |
908 | char *segsrc = linebuf + sr[i]; | |
3b5442f9 SC |
909 | supply_val (R0_REGNUM + i, 2, src); |
910 | supply_val (PR0_REGNUM + i, 4, src, segsrc); | |
edd01519 SC |
911 | } |
912 | } | |
913 | if (!gottok) | |
914 | { | |
3b5442f9 SC |
915 | hms_write_cr (""); |
916 | expect ("HMS>"); | |
edd01519 SC |
917 | } |
918 | } | |
919 | while (!gottok); | |
920 | } | |
921 | #endif | |
922 | ||
923 | #ifdef GDB_TARGET_IS_H8300 | |
1f46923f | 924 | static void |
ae0ea72e | 925 | hms_fetch_register (dummy) |
ec25d19b | 926 | int dummy; |
fa4b55a1 SC |
927 | { |
928 | #define REGREPLY_SIZE 79 | |
ec25d19b | 929 | char linebuf[REGREPLY_SIZE + 1]; |
fa4b55a1 | 930 | int i; |
ec25d19b | 931 | int s; |
fa4b55a1 | 932 | int gottok; |
ec25d19b | 933 | |
f4f0d174 | 934 | unsigned LONGEST reg[NUM_REGS]; |
ec25d19b SC |
935 | |
936 | check_open (); | |
937 | ||
938 | do | |
fa4b55a1 | 939 | { |
ec25d19b | 940 | hms_write_cr ("r"); |
3b5442f9 SC |
941 | |
942 | s = timed_read (linebuf, 1, 1); | |
943 | ||
944 | while (linebuf[0] != 'r') | |
945 | s = timed_read (linebuf, 1, 1); | |
946 | ||
947 | s = timed_read (linebuf + 1, REGREPLY_SIZE - 1, 1); | |
ec25d19b SC |
948 | |
949 | linebuf[REGREPLY_SIZE] = 0; | |
950 | gottok = 0; | |
951 | if (linebuf[0] == 'r' && | |
952 | linebuf[3] == 'P' && | |
953 | linebuf[4] == 'C' && | |
954 | linebuf[5] == '=' && | |
955 | linebuf[75] == 'H' && | |
956 | linebuf[76] == 'M' && | |
957 | linebuf[77] == 'S') | |
958 | { | |
959 | /* | |
03fc5a0b SC |
960 | PC=XXXX CCR=XX:XXXXXXXX R0-R7= XXXX XXXX XXXX XXXX XXXX XXXX XXXX XXXX |
961 | 5436789012345678901234567890123456789012345678901234567890123456789012 | |
962 | 0 1 2 3 4 5 6 | |
963 | */ | |
ec25d19b SC |
964 | gottok = 1; |
965 | ||
966 | reg[PC_REGNUM] = gethex (4, linebuf + 6, &gottok); | |
967 | reg[CCR_REGNUM] = gethex (2, linebuf + 15, &gottok); | |
968 | for (i = 0; i < 8; i++) | |
969 | { | |
970 | reg[i] = gethex (4, linebuf + 34 + 5 * i, &gottok); | |
971 | } | |
972 | } | |
fa4b55a1 | 973 | } |
fa4b55a1 | 974 | while (!gottok); |
ec25d19b SC |
975 | for (i = 0; i < NUM_REGS; i++) |
976 | { | |
977 | char swapped[2]; | |
fa4b55a1 | 978 | |
ec25d19b SC |
979 | swapped[1] = reg[i]; |
980 | swapped[0] = (reg[i]) >> 8; | |
fa4b55a1 | 981 | |
ec25d19b SC |
982 | supply_register (i, swapped); |
983 | } | |
984 | } | |
edd01519 | 985 | #endif |
fa4b55a1 SC |
986 | /* Store register REGNO, or all if REGNO == -1. |
987 | Return errno value. */ | |
ae0ea72e | 988 | static void |
fa4b55a1 SC |
989 | hms_store_register (regno) |
990 | int regno; | |
991 | { | |
ec25d19b | 992 | if (regno == -1) |
ae0ea72e | 993 | { |
ec25d19b SC |
994 | for (regno = 0; regno < NUM_REGS; regno++) |
995 | { | |
996 | hms_store_register (regno); | |
997 | } | |
ae0ea72e | 998 | } |
fa4b55a1 | 999 | else |
ec25d19b SC |
1000 | { |
1001 | char *name = get_reg_name (regno); | |
1002 | char buffer[100]; | |
3b5442f9 SC |
1003 | /* Some regs dont really exist */ |
1004 | if (!(name[0] == 'p' && name[1] == 'r') | |
1005 | && !(name[0] == 'c' && name[1] == 'y') | |
1006 | && !(name[0] == 't' && name[1] == 'i') | |
1007 | && !(name[0] == 'i' && name[1] == 'n')) | |
1008 | { | |
1009 | sprintf (buffer, "r %s=%x", name, read_register (regno)); | |
1010 | hms_write_cr (buffer); | |
1011 | expect_prompt (); | |
1012 | } | |
edd01519 | 1013 | } |
ec25d19b | 1014 | } |
ae0ea72e | 1015 | |
edd01519 | 1016 | |
fa4b55a1 SC |
1017 | /* Get ready to modify the registers array. On machines which store |
1018 | individual registers, this doesn't need to do anything. On machines | |
1019 | which store all the registers in one fell swoop, this makes sure | |
1020 | that registers contains all the registers from the program being | |
1021 | debugged. */ | |
1022 | ||
1023 | void | |
1024 | hms_prepare_to_store () | |
1025 | { | |
1026 | /* Do nothing, since we can store individual regs */ | |
1027 | } | |
1028 | ||
ec25d19b SC |
1029 | static CORE_ADDR |
1030 | translate_addr (addr) | |
1031 | CORE_ADDR addr; | |
fa4b55a1 SC |
1032 | { |
1033 | ||
ec25d19b | 1034 | return (addr); |
fa4b55a1 SC |
1035 | |
1036 | } | |
1037 | ||
1038 | /* Read a word from remote address ADDR and return it. | |
1039 | * This goes through the data cache. | |
1040 | */ | |
1041 | int | |
1042 | hms_fetch_word (addr) | |
1043 | CORE_ADDR addr; | |
1044 | { | |
5d747d61 | 1045 | return dcache_fetch (dcache_ptr, addr); |
fa4b55a1 SC |
1046 | } |
1047 | ||
1048 | /* Write a word WORD into remote address ADDR. | |
1049 | This goes through the data cache. */ | |
1050 | ||
1051 | void | |
1052 | hms_store_word (addr, word) | |
1053 | CORE_ADDR addr; | |
1054 | int word; | |
1055 | { | |
5d747d61 | 1056 | dcache_poke (dcache_ptr, addr, word); |
fa4b55a1 SC |
1057 | } |
1058 | ||
1059 | int | |
ec25d19b | 1060 | hms_xfer_inferior_memory (memaddr, myaddr, len, write, target) |
fa4b55a1 SC |
1061 | CORE_ADDR memaddr; |
1062 | char *myaddr; | |
1063 | int len; | |
1064 | int write; | |
ec25d19b | 1065 | struct target_ops *target; /* ignored */ |
fa4b55a1 SC |
1066 | { |
1067 | register int i; | |
ec25d19b | 1068 | |
fa4b55a1 | 1069 | /* Round starting address down to longword boundary. */ |
ec25d19b SC |
1070 | register CORE_ADDR addr; |
1071 | ||
fa4b55a1 SC |
1072 | /* Round ending address up; get number of longwords that makes. */ |
1073 | register int count; | |
ec25d19b | 1074 | |
fa4b55a1 | 1075 | /* Allocate buffer of that many longwords. */ |
ec25d19b | 1076 | register int *buffer; |
fa4b55a1 SC |
1077 | |
1078 | memaddr &= 0xffff; | |
ec25d19b SC |
1079 | addr = memaddr & -sizeof (int); |
1080 | count = (((memaddr + len) - addr) + sizeof (int) - 1) / sizeof (int); | |
fa4b55a1 | 1081 | |
ec25d19b | 1082 | buffer = (int *) alloca (count * sizeof (int)); |
1f46923f | 1083 | |
fa4b55a1 | 1084 | if (write) |
ec25d19b SC |
1085 | { |
1086 | /* Fill start and end extra bytes of buffer with existing memory data. */ | |
fa4b55a1 | 1087 | |
ec25d19b SC |
1088 | if (addr != memaddr || len < (int) sizeof (int)) |
1089 | { | |
1090 | /* Need part of initial word -- fetch it. */ | |
1091 | buffer[0] = hms_fetch_word (addr); | |
1092 | } | |
fa4b55a1 | 1093 | |
ec25d19b SC |
1094 | if (count > 1) /* FIXME, avoid if even boundary */ |
1095 | { | |
1096 | buffer[count - 1] | |
1097 | = hms_fetch_word (addr + (count - 1) * sizeof (int)); | |
1098 | } | |
fa4b55a1 | 1099 | |
ec25d19b | 1100 | /* Copy data to be written over corresponding part of buffer */ |
fa4b55a1 | 1101 | |
ade40d31 | 1102 | memcpy ((char *) buffer + (memaddr & (sizeof (int) - 1)), myaddr, len); |
fa4b55a1 | 1103 | |
ec25d19b | 1104 | /* Write the entire buffer. */ |
fa4b55a1 | 1105 | |
ec25d19b SC |
1106 | for (i = 0; i < count; i++, addr += sizeof (int)) |
1107 | { | |
1108 | errno = 0; | |
1109 | hms_store_word (addr, buffer[i]); | |
1110 | if (errno) | |
1111 | { | |
ec25d19b SC |
1112 | return 0; |
1113 | } | |
1114 | ||
1115 | } | |
fa4b55a1 | 1116 | } |
fa4b55a1 | 1117 | else |
fa4b55a1 | 1118 | { |
ec25d19b SC |
1119 | /* Read all the longwords */ |
1120 | for (i = 0; i < count; i++, addr += sizeof (int)) | |
1121 | { | |
1122 | errno = 0; | |
1123 | buffer[i] = hms_fetch_word (addr); | |
1124 | if (errno) | |
1125 | { | |
1126 | return 0; | |
1127 | } | |
1128 | QUIT; | |
1129 | } | |
fa4b55a1 | 1130 | |
ec25d19b | 1131 | /* Copy appropriate bytes out of the buffer. */ |
ade40d31 | 1132 | memcpy (myaddr, (char *) buffer + (memaddr & (sizeof (int) - 1)), len); |
ec25d19b | 1133 | } |
fa4b55a1 | 1134 | |
fa4b55a1 SC |
1135 | return len; |
1136 | } | |
1137 | ||
fa4b55a1 SC |
1138 | int |
1139 | hms_write_inferior_memory (memaddr, myaddr, len) | |
1140 | CORE_ADDR memaddr; | |
ae0ea72e | 1141 | unsigned char *myaddr; |
fa4b55a1 SC |
1142 | int len; |
1143 | { | |
ae0ea72e SC |
1144 | bfd_vma addr; |
1145 | int done; | |
ec25d19b | 1146 | int todo; |
3b5442f9 | 1147 | char buffer[100]; |
ae0ea72e | 1148 | done = 0; |
3b5442f9 SC |
1149 | hms_write_cr ("."); |
1150 | expect_prompt (); | |
ec25d19b | 1151 | while (done < len) |
ae0ea72e | 1152 | { |
3b5442f9 | 1153 | char *ptr = buffer; |
ec25d19b SC |
1154 | int thisgo; |
1155 | int idx; | |
1156 | ||
1157 | thisgo = len - done; | |
1158 | if (thisgo > 20) | |
1159 | thisgo = 20; | |
ae0ea72e | 1160 | |
3b5442f9 SC |
1161 | sprintf (ptr, "M.B %4x =", memaddr + done); |
1162 | ptr += 10; | |
ec25d19b SC |
1163 | for (idx = 0; idx < thisgo; idx++) |
1164 | { | |
3b5442f9 SC |
1165 | sprintf (ptr, "%2x ", myaddr[idx + done]); |
1166 | ptr += 3; | |
ec25d19b | 1167 | } |
3b5442f9 | 1168 | hms_write_cr (buffer); |
ec25d19b SC |
1169 | expect_prompt (); |
1170 | done += thisgo; | |
1171 | } | |
fa4b55a1 SC |
1172 | } |
1173 | ||
1174 | void | |
1175 | hms_files_info () | |
1176 | { | |
ec25d19b SC |
1177 | char *file = "nothing"; |
1178 | ||
1179 | if (exec_bfd) | |
1180 | file = bfd_get_filename (exec_bfd); | |
ae0ea72e | 1181 | |
ec25d19b | 1182 | if (exec_bfd) |
ae0ea72e | 1183 | #ifdef __GO32__ |
ec25d19b | 1184 | printf_filtered ("\tAttached to DOS asynctsr and running program %s\n", file); |
ae0ea72e | 1185 | #else |
5905161c | 1186 | printf_filtered ("\tAttached to %s at %d baud and running program %s\n", dev_name, baudrate, file); |
ae0ea72e | 1187 | #endif |
ec25d19b | 1188 | printf_filtered ("\ton an H8/300 processor.\n"); |
fa4b55a1 SC |
1189 | } |
1190 | ||
1191 | /* Copy LEN bytes of data from debugger memory at MYADDR | |
ec25d19b | 1192 | to inferior's memory at MEMADDR. Returns errno value. |
03fc5a0b | 1193 | * sb/sh instructions don't work on unaligned addresses, when TU=1. |
fa4b55a1 SC |
1194 | */ |
1195 | ||
fa4b55a1 SC |
1196 | /* Read LEN bytes from inferior memory at MEMADDR. Put the result |
1197 | at debugger address MYADDR. Returns errno value. */ | |
1198 | int | |
ec25d19b | 1199 | hms_read_inferior_memory (memaddr, myaddr, len) |
fa4b55a1 SC |
1200 | CORE_ADDR memaddr; |
1201 | char *myaddr; | |
1202 | int len; | |
1203 | { | |
1204 | /* Align to nearest low 16 bits */ | |
1205 | int i; | |
ec25d19b | 1206 | |
fa4b55a1 | 1207 | CORE_ADDR start = memaddr; |
ec25d19b SC |
1208 | CORE_ADDR end = memaddr + len - 1; |
1209 | ||
1210 | int ok = 1; | |
1211 | ||
fa4b55a1 | 1212 | /* |
03fc5a0b SC |
1213 | AAAA: XXXX XXXX XXXX XXXX XXXX XXXX XXXX XXXX '................' |
1214 | 012345678901234567890123456789012345678901234567890123456789012345 | |
1215 | 0 1 2 3 4 5 6 | |
1216 | */ | |
fa4b55a1 | 1217 | char buffer[66]; |
ec25d19b SC |
1218 | |
1219 | if (memaddr & 0xf) | |
1220 | abort (); | |
1221 | if (len != 16) | |
1222 | abort (); | |
1223 | ||
1224 | sprintf (buffer, "m %4x %4x", start & 0xffff, end & 0xffff); | |
402b0d2e | 1225 | |
03fc5a0b | 1226 | flush (); |
ec25d19b | 1227 | hms_write_cr (buffer); |
03fc5a0b | 1228 | /* drop the echo and newline */ |
fa4b55a1 | 1229 | for (i = 0; i < 13; i++) |
ec25d19b | 1230 | readchar (); |
fa4b55a1 | 1231 | |
fa4b55a1 SC |
1232 | /* Grab the lines as they come out and fill the area */ |
1233 | /* Skip over cr */ | |
ec25d19b | 1234 | while (1) |
fa4b55a1 | 1235 | { |
ec25d19b SC |
1236 | int p; |
1237 | int i; | |
1238 | int addr; | |
1239 | size_t idx; | |
fa4b55a1 | 1240 | |
ec25d19b SC |
1241 | char byte[16]; |
1242 | ||
1243 | buffer[0] = readchar (); | |
03fc5a0b | 1244 | while (buffer[0] == '\r' |
a87594a5 SC |
1245 | || buffer[0] == '\n') |
1246 | buffer[0] = readchar (); | |
1247 | ||
ec25d19b SC |
1248 | if (buffer[0] == 'M') |
1249 | break; | |
402b0d2e | 1250 | |
03fc5a0b SC |
1251 | for (i = 1; i < 50; i++) |
1252 | { | |
1253 | buffer[i] = readchar (); | |
1254 | } | |
402b0d2e | 1255 | /* sometimes we loose characters in the ascii representation of the |
03fc5a0b SC |
1256 | data. I don't know where. So just scan for the end of line */ |
1257 | i = readchar (); | |
402b0d2e | 1258 | while (i != '\n' && i != '\r') |
03fc5a0b SC |
1259 | i = readchar (); |
1260 | ||
ec25d19b SC |
1261 | /* Now parse the line */ |
1262 | ||
1263 | addr = gethex (4, buffer, &ok); | |
1264 | idx = 6; | |
1265 | for (p = 0; p < 16; p += 2) | |
1266 | { | |
1267 | byte[p] = gethex (2, buffer + idx, &ok); | |
1268 | byte[p + 1] = gethex (2, buffer + idx + 2, &ok); | |
1269 | idx += 5; | |
ec25d19b SC |
1270 | } |
1271 | ||
1272 | for (p = 0; p < 16; p++) | |
1273 | { | |
1274 | if (addr + p >= memaddr && | |
1275 | addr + p < memaddr + len) | |
1276 | { | |
1277 | myaddr[(addr + p) - memaddr] = byte[p]; | |
1278 | ||
1279 | } | |
1280 | ||
1281 | } | |
fa4b55a1 | 1282 | } |
3b5442f9 SC |
1283 | #ifdef GDB_TARGET_IS_H8500 |
1284 | expect ("ore>"); | |
edd01519 | 1285 | #endif |
3b5442f9 | 1286 | #ifdef GDB_TARGET_IS_H8300 |
a493d9a6 | 1287 | expect ("emory>"); |
edd01519 | 1288 | #endif |
3b5442f9 SC |
1289 | hms_write_cr ("."); |
1290 | ||
ec25d19b | 1291 | expect_prompt (); |
fa4b55a1 | 1292 | return len; |
fa4b55a1 SC |
1293 | } |
1294 | ||
edd01519 | 1295 | |
fa4b55a1 | 1296 | |
fa4b55a1 | 1297 | #define MAX_BREAKS 16 |
ec25d19b | 1298 | static int num_brkpts = 0; |
fa4b55a1 | 1299 | static int |
ec25d19b SC |
1300 | hms_insert_breakpoint (addr, save) |
1301 | CORE_ADDR addr; | |
1302 | char *save; /* Throw away, let hms save instructions */ | |
fa4b55a1 | 1303 | { |
ec25d19b SC |
1304 | check_open (); |
1305 | ||
1306 | if (num_brkpts < MAX_BREAKS) | |
1307 | { | |
1308 | char buffer[100]; | |
fa4b55a1 | 1309 | |
ec25d19b SC |
1310 | num_brkpts++; |
1311 | sprintf (buffer, "b %x", addr & 0xffff); | |
1312 | hms_write_cr (buffer); | |
1313 | expect_prompt (); | |
1314 | return (0); | |
1315 | } | |
1316 | else | |
1317 | { | |
199b2450 | 1318 | fprintf_filtered (gdb_stderr, |
ec25d19b SC |
1319 | "Too many break points, break point not installed\n"); |
1320 | return (1); | |
1321 | } | |
fa4b55a1 SC |
1322 | |
1323 | } | |
1324 | static int | |
ec25d19b SC |
1325 | hms_remove_breakpoint (addr, save) |
1326 | CORE_ADDR addr; | |
1327 | char *save; /* Throw away, let hms save instructions */ | |
fa4b55a1 | 1328 | { |
ec25d19b SC |
1329 | if (num_brkpts > 0) |
1330 | { | |
1331 | char buffer[100]; | |
1332 | ||
1333 | num_brkpts--; | |
1334 | sprintf (buffer, "b - %x", addr & 0xffff); | |
1335 | hms_write_cr (buffer); | |
1336 | expect_prompt (); | |
1337 | ||
1338 | } | |
1339 | return (0); | |
fa4b55a1 SC |
1340 | } |
1341 | ||
1342 | /* Clear the hmss notion of what the break points are */ | |
1343 | static int | |
ec25d19b SC |
1344 | hms_clear_breakpoints () |
1345 | { | |
fa4b55a1 | 1346 | |
ec25d19b SC |
1347 | if (is_open) |
1348 | { | |
1349 | hms_write_cr ("b -"); | |
1350 | expect_prompt (); | |
1351 | } | |
fa4b55a1 | 1352 | num_brkpts = 0; |
fa4b55a1 SC |
1353 | } |
1354 | static void | |
ec25d19b SC |
1355 | hms_mourn () |
1356 | { | |
1357 | hms_clear_breakpoints (); | |
71607f9d | 1358 | unpush_target (&hms_ops); |
fa4b55a1 | 1359 | generic_mourn_inferior (); |
fa4b55a1 SC |
1360 | } |
1361 | ||
fa4b55a1 | 1362 | /* Put a command string, in args, out to the hms. The hms is assumed to |
ae0ea72e | 1363 | be in raw mode, all writing/reading done through desc. |
fa4b55a1 SC |
1364 | Ouput from the hms is placed on the users terminal until the |
1365 | prompt from the hms is seen. | |
1366 | FIXME: Can't handle commands that take input. */ | |
1367 | ||
1368 | void | |
1369 | hms_com (args, fromtty) | |
ec25d19b SC |
1370 | char *args; |
1371 | int fromtty; | |
fa4b55a1 | 1372 | { |
ec25d19b SC |
1373 | check_open (); |
1374 | ||
1375 | if (!args) | |
1376 | return; | |
1377 | ||
fa4b55a1 SC |
1378 | /* Clear all input so only command relative output is displayed */ |
1379 | ||
ec25d19b | 1380 | hms_write_cr (args); |
03fc5a0b SC |
1381 | /* hms_write ("\030", 1); */ |
1382 | expect_prompt (); | |
1383 | } | |
1384 | ||
1385 | static void | |
1386 | hms_open (name, from_tty) | |
1387 | char *name; | |
1388 | int from_tty; | |
1389 | { | |
1390 | unsigned int prl; | |
1391 | char *p; | |
1392 | ||
1393 | if (name == 0) | |
1394 | { | |
1395 | name = ""; | |
1396 | } | |
1397 | if (is_open) | |
1398 | hms_close (0); | |
1399 | dev_name = strdup (name); | |
1400 | ||
1401 | if (!(desc = SERIAL_OPEN (dev_name))) | |
1402 | perror_with_name ((char *) dev_name); | |
1403 | ||
1404 | SERIAL_RAW (desc); | |
1405 | is_open = 1; | |
1406 | push_target (&hms_ops); | |
5d747d61 SC |
1407 | dcache_ptr = dcache_init (hms_read_inferior_memory, |
1408 | hms_write_inferior_memory); | |
1409 | remote_dcache = 1; | |
03fc5a0b SC |
1410 | /* Hello? Are you there? */ |
1411 | SERIAL_WRITE (desc, "\r\n", 2); | |
ec25d19b | 1412 | expect_prompt (); |
03fc5a0b SC |
1413 | |
1414 | /* Clear any break points */ | |
1415 | hms_clear_breakpoints (); | |
1416 | ||
1417 | printf_filtered ("Connected to remote board running HMS monitor.\n"); | |
1418 | add_commands (); | |
1419 | /* hms_drain (); */ | |
fa4b55a1 SC |
1420 | } |
1421 | ||
1422 | /* Define the target subroutine names */ | |
1423 | ||
ec25d19b SC |
1424 | struct target_ops hms_ops = |
1425 | { | |
1426 | "hms", "Remote HMS monitor", | |
1427 | "Use the H8 evaluation board running the HMS monitor connected\n\ | |
fa4b55a1 SC |
1428 | by a serial line.", |
1429 | ||
ec25d19b SC |
1430 | hms_open, hms_close, |
1431 | 0, hms_detach, hms_resume, hms_wait, /* attach */ | |
1432 | hms_fetch_register, hms_store_register, | |
1433 | hms_prepare_to_store, | |
1434 | hms_xfer_inferior_memory, | |
1435 | hms_files_info, | |
03fc5a0b | 1436 | hms_insert_breakpoint, hms_remove_breakpoint, /* Breakpoints */ |
ec25d19b SC |
1437 | 0, 0, 0, 0, 0, /* Terminal handling */ |
1438 | hms_kill, /* FIXME, kill */ | |
d2d0e51d | 1439 | gr_load_image, |
ec25d19b SC |
1440 | 0, /* lookup_symbol */ |
1441 | hms_create_inferior, /* create_inferior */ | |
1442 | hms_mourn, /* mourn_inferior FIXME */ | |
1443 | 0, /* can_run */ | |
1444 | 0, /* notice_signals */ | |
78b459a7 | 1445 | 0, /* to_stop */ |
ec25d19b SC |
1446 | process_stratum, 0, /* next */ |
1447 | 1, 1, 1, 1, 1, /* all mem, mem, stack, regs, exec */ | |
1448 | 0, 0, /* Section pointers */ | |
1449 | OPS_MAGIC, /* Always the last thing */ | |
fa4b55a1 SC |
1450 | }; |
1451 | ||
03fc5a0b | 1452 | hms_quiet () /* FIXME - this routine can be removed after Dec '94 */ |
fa4b55a1 | 1453 | { |
ec25d19b SC |
1454 | quiet = !quiet; |
1455 | if (quiet) | |
1456 | printf_filtered ("Snoop disabled\n"); | |
1457 | else | |
1458 | printf_filtered ("Snoop enabled\n"); | |
ae0ea72e | 1459 | |
03fc5a0b | 1460 | printf_filtered ("`snoop' is obsolete, please use `set remotedebug'.\n"); |
fa4b55a1 SC |
1461 | } |
1462 | ||
ec25d19b SC |
1463 | hms_device (s) |
1464 | char *s; | |
fa4b55a1 | 1465 | { |
ec25d19b SC |
1466 | if (s) |
1467 | { | |
1468 | dev_name = get_word (&s); | |
1469 | } | |
fa4b55a1 SC |
1470 | } |
1471 | ||
ec25d19b SC |
1472 | static |
1473 | hms_speed (s) | |
1474 | char *s; | |
fa4b55a1 | 1475 | { |
ec25d19b SC |
1476 | check_open (); |
1477 | ||
1478 | if (s) | |
1479 | { | |
1480 | char buffer[100]; | |
1481 | int newrate = atoi (s); | |
1482 | int which = 0; | |
1483 | ||
a493d9a6 | 1484 | if (SERIAL_SETBAUDRATE (desc, newrate)) |
ec25d19b SC |
1485 | error ("Can't use %d baud\n", newrate); |
1486 | ||
1487 | printf_filtered ("Checking target is in sync\n"); | |
1488 | ||
ec25d19b SC |
1489 | printf_filtered ("Sending commands to set target to %d\n", |
1490 | baudrate); | |
1491 | ||
1492 | sprintf (buffer, "tm %d. N 8 1", baudrate); | |
1493 | hms_write_cr (buffer); | |
1494 | } | |
fa4b55a1 SC |
1495 | } |
1496 | ||
1497 | /***********************************************************************/ | |
1498 | ||
3b5442f9 SC |
1499 | static void |
1500 | hms_drain (args, fromtty) | |
1501 | char *args; | |
1502 | int fromtty; | |
3b5442f9 SC |
1503 | { |
1504 | int c; | |
1505 | while (1) | |
1506 | { | |
1507 | c = SERIAL_READCHAR (desc, 1); | |
1508 | if (c == SERIAL_TIMEOUT) | |
1509 | break; | |
1510 | if (c == SERIAL_ERROR) | |
1511 | break; | |
1512 | if (c > ' ' && c < 127) | |
1513 | printf ("%c", c & 0xff); | |
1514 | else | |
1515 | printf ("<%x>", c & 0xff); | |
1516 | } | |
1517 | } | |
1518 | ||
1519 | static void | |
1520 | add_commands () | |
1521 | { | |
1522 | ||
402b0d2e | 1523 | add_com ("hms_drain", class_obscure, hms_drain, |
3b5442f9 SC |
1524 | "Drain pending hms text buffers."); |
1525 | } | |
1526 | ||
1527 | static void | |
1528 | remove_commands () | |
1529 | { | |
1530 | extern struct cmd_list_element *cmdlist; | |
1531 | delete_cmd ("hms-drain", &cmdlist); | |
1532 | } | |
1533 | ||
03fc5a0b | 1534 | |
fa4b55a1 SC |
1535 | void |
1536 | _initialize_remote_hms () | |
1537 | { | |
1538 | add_target (&hms_ops); | |
ec25d19b | 1539 | |
fa4b55a1 | 1540 | add_com ("hms <command>", class_obscure, hms_com, |
ec25d19b | 1541 | "Send a command to the HMS monitor."); |
791d4d7d | 1542 | |
03fc5a0b | 1543 | /* FIXME - hms_quiet and `snoop' can be removed after Dec '94 */ |
fa4b55a1 | 1544 | add_com ("snoop", class_obscure, hms_quiet, |
791d4d7d | 1545 | "Show what commands are going to the monitor (OBSOLETE - see 'set remotedebug')"); |
ae0ea72e | 1546 | |
fa4b55a1 SC |
1547 | add_com ("device", class_obscure, hms_device, |
1548 | "Set the terminal line for HMS communications"); | |
1549 | ||
1550 | add_com ("speed", class_obscure, hms_speed, | |
1551 | "Set the terminal line speed for HMS communications"); | |
ec25d19b | 1552 | |
3ec5a74b | 1553 | dev_name = NULL; |
fa4b55a1 | 1554 | } |
5d747d61 SC |
1555 | #endif |
1556 |