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