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