* config/m68k/monitor.mt (TDEPFILE): Add remote-es.o.
[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 */
45dc9be3 488 proceed (entry_pt, TARGET_SIGNAL_DEFAULT, 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 641hms_resume (pid, step, sig)
67ac9759
JK
642 int pid, step;
643 enum target_signal sig;
fa4b55a1 644{
ec25d19b
SC
645 dcache_flush ();
646
647 if (step)
648 {
649 hms_write_cr ("s");
650 expect ("Step>");
651
652 /* Force the next hms_wait to return a trap. Not doing anything
fa4b55a1
SC
653 about I/O from the target means that the user has to type
654 "continue" to see any. FIXME, this should be fixed. */
ec25d19b
SC
655 need_artificial_trap = 1;
656 }
fa4b55a1 657 else
ec25d19b
SC
658 {
659 hms_write_cr ("g");
660 expect ("g");
661 }
fa4b55a1
SC
662}
663
664/* Wait until the remote machine stops, then return,
665 storing status in STATUS just as `wait' would. */
666
667int
de43d7d0
SG
668hms_wait (pid, status)
669 int pid;
67ac9759 670 struct target_waitstatus *status;
fa4b55a1 671{
ec25d19b 672 /* Strings to look for. '?' means match any single character.
fa4b55a1
SC
673 Note that with the algorithm we use, the initial character
674 of the string cannot recur in the string, or we will not
675 find some cases of the string in the input. */
ec25d19b 676
96743d3c 677 static char bpt[] = "At breakpoint:";
ec25d19b 678
fa4b55a1
SC
679 /* It would be tempting to look for "\n[__exit + 0x8]\n"
680 but that requires loading symbols with "yc i" and even if
681 we did do that we don't know that the file has symbols. */
682 static char exitmsg[] = "HMS>";
683 char *bp = bpt;
684 char *ep = exitmsg;
685
686 /* Large enough for either sizeof (bpt) or sizeof (exitmsg) chars. */
687 char swallowed[50];
ec25d19b 688
fa4b55a1
SC
689 /* Current position in swallowed. */
690 char *swallowed_p = swallowed;
691
692 int ch;
693 int ch_handled;
694 int old_timeout = timeout;
695 int old_immediate_quit = immediate_quit;
1f46923f 696 int swallowed_cr = 0;
ec25d19b 697
67ac9759
JK
698 status->kind = TARGET_WAITKIND_EXITED;
699 status->value.integer = 0;
fa4b55a1
SC
700
701 if (need_artificial_trap != 0)
ec25d19b 702 {
67ac9759
JK
703 status->kind = TARGET_WAITKIND_STOPPED;
704 status->value.sig = TARGET_SIGNAL_TRAP;
ec25d19b
SC
705 need_artificial_trap--;
706 return 0;
707 }
fa4b55a1 708
e93790f0 709 timeout = -1; /* Don't time out -- user program is running. */
1f46923f 710 immediate_quit = 1; /* Helps ability to QUIT */
ec25d19b 711 while (1)
96743d3c 712 {
ec25d19b
SC
713 QUIT; /* Let user quit and leave process running */
714 ch_handled = 0;
715 ch = readchar ();
716 if (ch == *bp)
717 {
718 bp++;
719 if (*bp == '\0')
720 break;
721 ch_handled = 1;
722
723 *swallowed_p++ = ch;
724 }
725 else
726 {
727 bp = bpt;
728 }
729 if (ch == *ep || *ep == '?')
730 {
731 ep++;
732 if (*ep == '\0')
733 break;
734
735 if (!ch_handled)
736 *swallowed_p++ = ch;
737 ch_handled = 1;
738 }
739 else
740 {
741 ep = exitmsg;
742 }
743
744 if (!ch_handled)
745 {
746 char *p;
747
748 /* Print out any characters which have been swallowed. */
749 for (p = swallowed; p < swallowed_p; ++p)
753a74d9 750 putc_unfiltered (*p);
ec25d19b
SC
751 swallowed_p = swallowed;
752
753 if ((ch != '\r' && ch != '\n') || swallowed_cr > 10)
754 {
753a74d9 755 putc_unfiltered (ch);
ec25d19b
SC
756 swallowed_cr = 10;
757 }
758 swallowed_cr++;
759
760 }
96743d3c 761 }
ec25d19b 762 if (*bp == '\0')
96743d3c 763 {
67ac9759
JK
764 status->kind = TARGET_WAITKIND_STOPPED;
765 status->value.sig = TARGET_SIGNAL_TRAP;
ec25d19b
SC
766 expect_prompt ();
767 }
768 else
96743d3c 769 {
67ac9759
JK
770 status->kind = TARGET_WAITKIND_EXITED;
771 status->value.integer = 0;
96743d3c 772 }
ec25d19b 773
fa4b55a1
SC
774 timeout = old_timeout;
775 immediate_quit = old_immediate_quit;
fa4b55a1
SC
776 return 0;
777}
778
779/* Return the name of register number REGNO
780 in the form input and output by hms.
781
782 Returns a pointer to a static buffer containing the answer. */
783static char *
784get_reg_name (regno)
785 int regno;
786{
62b66d6d 787 static char *rn[] = REGISTER_NAMES;
ec25d19b 788
fa4b55a1 789 return rn[regno];
fa4b55a1
SC
790}
791
792/* Read the remote registers. */
a493d9a6 793static int
ec25d19b
SC
794gethex (length, start, ok)
795 unsigned int length;
796 char *start;
797 int *ok;
fa4b55a1
SC
798{
799 int result = 0;
ec25d19b
SC
800
801 while (length--)
fa4b55a1 802 {
ec25d19b
SC
803 result <<= 4;
804 if (*start >= 'a' && *start <= 'f')
805 {
806 result += *start - 'a' + 10;
807 }
808 else if (*start >= 'A' && *start <= 'F')
809 {
810 result += *start - 'A' + 10;
811 }
812 else if (*start >= '0' && *start <= '9')
813 {
814 result += *start - '0';
815 }
816 else
817 *ok = 0;
818 start++;
819
fa4b55a1 820 }
fa4b55a1
SC
821 return result;
822}
ec25d19b
SC
823static int
824timed_read (buf, n, timeout)
825 char *buf;
fa4b55a1
SC
826
827{
828 int i;
829 char c;
ec25d19b 830
fa4b55a1 831 i = 0;
ec25d19b
SC
832 while (i < n)
833 {
834 c = readchar ();
835
836 if (c == 0)
837 return i;
838 buf[i] = c;
839 i++;
840
841 }
842 return i;
fa4b55a1 843}
ec25d19b
SC
844
845hms_write (a, l)
846 char *a;
fa4b55a1
SC
847{
848 int i;
ec25d19b 849
a493d9a6 850 SERIAL_WRITE (desc, a, l);
ae0ea72e 851
96743d3c 852 if (!quiet)
ec25d19b
SC
853 for (i = 0; i < l; i++)
854 {
199b2450 855 printf_unfiltered ("%c", a[i]);
ec25d19b 856 }
fa4b55a1
SC
857}
858
ec25d19b
SC
859hms_write_cr (s)
860 char *s;
fa4b55a1 861{
ec25d19b
SC
862 hms_write (s, strlen (s));
863 hms_write ("\r", 1);
1f46923f
SC
864}
865
866static void
ae0ea72e 867hms_fetch_register (dummy)
ec25d19b 868 int dummy;
fa4b55a1
SC
869{
870#define REGREPLY_SIZE 79
ec25d19b 871 char linebuf[REGREPLY_SIZE + 1];
fa4b55a1 872 int i;
ec25d19b 873 int s;
fa4b55a1 874 int gottok;
ec25d19b 875
f4f0d174 876 unsigned LONGEST reg[NUM_REGS];
1f46923f 877 int foo[8];
ec25d19b
SC
878
879 check_open ();
880
881 do
fa4b55a1 882 {
ec25d19b
SC
883
884 hms_write_cr ("r");
885 s = timed_read (linebuf, REGREPLY_SIZE, 1);
886
887 linebuf[REGREPLY_SIZE] = 0;
888 gottok = 0;
889 if (linebuf[0] == 'r' &&
890 linebuf[3] == 'P' &&
891 linebuf[4] == 'C' &&
892 linebuf[5] == '=' &&
893 linebuf[75] == 'H' &&
894 linebuf[76] == 'M' &&
895 linebuf[77] == 'S')
896 {
897 /*
fa4b55a1
SC
898 PC=XXXX CCR=XX:XXXXXXXX R0-R7= XXXX XXXX XXXX XXXX XXXX XXXX XXXX XXXX
899 5436789012345678901234567890123456789012345678901234567890123456789012
ec25d19b 900 0 1 2 3 4 5 6
fa4b55a1 901 */
ec25d19b
SC
902 gottok = 1;
903
904 reg[PC_REGNUM] = gethex (4, linebuf + 6, &gottok);
905 reg[CCR_REGNUM] = gethex (2, linebuf + 15, &gottok);
906 for (i = 0; i < 8; i++)
907 {
908 reg[i] = gethex (4, linebuf + 34 + 5 * i, &gottok);
909 }
910 }
fa4b55a1 911 }
fa4b55a1 912 while (!gottok);
ec25d19b
SC
913 for (i = 0; i < NUM_REGS; i++)
914 {
915 char swapped[2];
fa4b55a1 916
ec25d19b
SC
917 swapped[1] = reg[i];
918 swapped[0] = (reg[i]) >> 8;
fa4b55a1 919
ec25d19b
SC
920 supply_register (i, swapped);
921 }
922}
fa4b55a1
SC
923
924/* Store register REGNO, or all if REGNO == -1.
925 Return errno value. */
ae0ea72e 926static void
fa4b55a1
SC
927hms_store_register (regno)
928 int regno;
929{
ec25d19b 930 if (regno == -1)
ae0ea72e 931 {
ec25d19b
SC
932 for (regno = 0; regno < NUM_REGS; regno++)
933 {
934 hms_store_register (regno);
935 }
ae0ea72e 936 }
fa4b55a1 937 else
ec25d19b
SC
938 {
939 char *name = get_reg_name (regno);
940 char buffer[100];
ae0ea72e 941
ec25d19b
SC
942 sprintf (buffer, "r %s=%x", name, read_register (regno));
943 hms_write_cr (buffer);
944 expect_prompt ();
945 }
946}
ae0ea72e 947
fa4b55a1
SC
948/* Get ready to modify the registers array. On machines which store
949 individual registers, this doesn't need to do anything. On machines
950 which store all the registers in one fell swoop, this makes sure
951 that registers contains all the registers from the program being
952 debugged. */
953
954void
955hms_prepare_to_store ()
956{
957 /* Do nothing, since we can store individual regs */
958}
959
ec25d19b
SC
960static CORE_ADDR
961translate_addr (addr)
962 CORE_ADDR addr;
fa4b55a1
SC
963{
964
ec25d19b 965 return (addr);
fa4b55a1
SC
966
967}
968
969/* Read a word from remote address ADDR and return it.
970 * This goes through the data cache.
971 */
972int
973hms_fetch_word (addr)
974 CORE_ADDR addr;
975{
ec25d19b 976 return dcache_fetch (addr);
fa4b55a1
SC
977}
978
979/* Write a word WORD into remote address ADDR.
980 This goes through the data cache. */
981
982void
983hms_store_word (addr, word)
984 CORE_ADDR addr;
985 int word;
986{
ec25d19b 987 dcache_poke (addr, word);
fa4b55a1
SC
988}
989
990int
ec25d19b 991hms_xfer_inferior_memory (memaddr, myaddr, len, write, target)
fa4b55a1
SC
992 CORE_ADDR memaddr;
993 char *myaddr;
994 int len;
995 int write;
ec25d19b 996 struct target_ops *target; /* ignored */
fa4b55a1
SC
997{
998 register int i;
ec25d19b 999
fa4b55a1 1000 /* Round starting address down to longword boundary. */
ec25d19b
SC
1001 register CORE_ADDR addr;
1002
fa4b55a1
SC
1003 /* Round ending address up; get number of longwords that makes. */
1004 register int count;
ec25d19b 1005
fa4b55a1 1006 /* Allocate buffer of that many longwords. */
ec25d19b 1007 register int *buffer;
fa4b55a1
SC
1008
1009 memaddr &= 0xffff;
ec25d19b
SC
1010 addr = memaddr & -sizeof (int);
1011 count = (((memaddr + len) - addr) + sizeof (int) - 1) / sizeof (int);
fa4b55a1 1012
ec25d19b 1013 buffer = (int *) alloca (count * sizeof (int));
1f46923f 1014
fa4b55a1 1015 if (write)
ec25d19b
SC
1016 {
1017 /* Fill start and end extra bytes of buffer with existing memory data. */
fa4b55a1 1018
ec25d19b
SC
1019 if (addr != memaddr || len < (int) sizeof (int))
1020 {
1021 /* Need part of initial word -- fetch it. */
1022 buffer[0] = hms_fetch_word (addr);
1023 }
fa4b55a1 1024
ec25d19b
SC
1025 if (count > 1) /* FIXME, avoid if even boundary */
1026 {
1027 buffer[count - 1]
1028 = hms_fetch_word (addr + (count - 1) * sizeof (int));
1029 }
fa4b55a1 1030
ec25d19b 1031 /* Copy data to be written over corresponding part of buffer */
fa4b55a1 1032
ade40d31 1033 memcpy ((char *) buffer + (memaddr & (sizeof (int) - 1)), myaddr, len);
fa4b55a1 1034
ec25d19b 1035 /* Write the entire buffer. */
fa4b55a1 1036
ec25d19b
SC
1037 for (i = 0; i < count; i++, addr += sizeof (int))
1038 {
1039 errno = 0;
1040 hms_store_word (addr, buffer[i]);
1041 if (errno)
1042 {
1043
1044 return 0;
1045 }
1046
1047 }
fa4b55a1 1048 }
fa4b55a1 1049 else
fa4b55a1 1050 {
ec25d19b
SC
1051 /* Read all the longwords */
1052 for (i = 0; i < count; i++, addr += sizeof (int))
1053 {
1054 errno = 0;
1055 buffer[i] = hms_fetch_word (addr);
1056 if (errno)
1057 {
1058 return 0;
1059 }
1060 QUIT;
1061 }
fa4b55a1 1062
ec25d19b 1063 /* Copy appropriate bytes out of the buffer. */
ade40d31 1064 memcpy (myaddr, (char *) buffer + (memaddr & (sizeof (int) - 1)), len);
ec25d19b 1065 }
fa4b55a1 1066
fa4b55a1
SC
1067 return len;
1068}
1069
fa4b55a1
SC
1070int
1071hms_write_inferior_memory (memaddr, myaddr, len)
1072 CORE_ADDR memaddr;
ae0ea72e 1073 unsigned char *myaddr;
fa4b55a1
SC
1074 int len;
1075{
ae0ea72e
SC
1076 bfd_vma addr;
1077 int done;
ec25d19b
SC
1078 int todo;
1079
ae0ea72e 1080 done = 0;
ec25d19b 1081 while (done < len)
ae0ea72e 1082 {
ec25d19b
SC
1083 char buffer[20];
1084 int thisgo;
1085 int idx;
1086
1087 thisgo = len - done;
1088 if (thisgo > 20)
1089 thisgo = 20;
ae0ea72e 1090
ec25d19b
SC
1091 sprintf (buffer, "M.B %4x =", memaddr + done);
1092 hms_write (buffer, 10);
1093 for (idx = 0; idx < thisgo; idx++)
1094 {
1095 char buf[20];
1096
1097 sprintf (buf, "%2x ", myaddr[idx + done]);
1098 hms_write (buf, 3);
1099 }
1100 hms_write_cr ("");
1101 expect_prompt ();
1102 done += thisgo;
1103 }
fa4b55a1 1104
fa4b55a1
SC
1105}
1106
1107void
1108hms_files_info ()
1109{
ec25d19b
SC
1110 char *file = "nothing";
1111
1112 if (exec_bfd)
1113 file = bfd_get_filename (exec_bfd);
ae0ea72e 1114
ec25d19b 1115 if (exec_bfd)
ae0ea72e 1116#ifdef __GO32__
ec25d19b 1117 printf_filtered ("\tAttached to DOS asynctsr and running program %s\n", file);
ae0ea72e 1118#else
5905161c 1119 printf_filtered ("\tAttached to %s at %d baud and running program %s\n", dev_name, baudrate, file);
ae0ea72e 1120#endif
ec25d19b 1121 printf_filtered ("\ton an H8/300 processor.\n");
fa4b55a1
SC
1122}
1123
1124/* Copy LEN bytes of data from debugger memory at MYADDR
ec25d19b
SC
1125 to inferior's memory at MEMADDR. Returns errno value.
1126 * sb/sh instructions don't work on unaligned addresses, when TU=1.
fa4b55a1
SC
1127 */
1128
fa4b55a1
SC
1129/* Read LEN bytes from inferior memory at MEMADDR. Put the result
1130 at debugger address MYADDR. Returns errno value. */
1131int
ec25d19b 1132hms_read_inferior_memory (memaddr, myaddr, len)
fa4b55a1
SC
1133 CORE_ADDR memaddr;
1134 char *myaddr;
1135 int len;
1136{
1137 /* Align to nearest low 16 bits */
1138 int i;
ec25d19b 1139
fa4b55a1
SC
1140#if 0
1141 CORE_ADDR start = memaddr & ~0xf;
ec25d19b
SC
1142 CORE_ADDR end = ((memaddr + len + 16) & ~0xf) - 1;
1143
fa4b55a1
SC
1144#endif
1145 CORE_ADDR start = memaddr;
ec25d19b
SC
1146 CORE_ADDR end = memaddr + len - 1;
1147
1148 int ok = 1;
1149
fa4b55a1
SC
1150 /*
1151 AAAA: XXXX XXXX XXXX XXXX XXXX XXXX XXXX XXXX '................'
1152 012345678901234567890123456789012345678901234567890123456789012345
1153 0 1 2 3 4 5 6
1154 */
1155 char buffer[66];
ec25d19b
SC
1156
1157 if (memaddr & 0xf)
1158 abort ();
1159 if (len != 16)
1160 abort ();
1161
1162 sprintf (buffer, "m %4x %4x", start & 0xffff, end & 0xffff);
1163 hms_write_cr (buffer);
fa4b55a1
SC
1164 /* drop the echo and newline*/
1165 for (i = 0; i < 13; i++)
ec25d19b 1166 readchar ();
fa4b55a1 1167
fa4b55a1
SC
1168 /* Grab the lines as they come out and fill the area */
1169 /* Skip over cr */
ec25d19b 1170 while (1)
fa4b55a1 1171 {
ec25d19b
SC
1172 int p;
1173 int i;
1174 int addr;
1175 size_t idx;
fa4b55a1 1176
ec25d19b
SC
1177 char byte[16];
1178
1179 buffer[0] = readchar ();
1180 if (buffer[0] == 'M')
1181 break;
1182 for (i = 1; i < 66; i++)
1183 buffer[i] = readchar ();
1184
1185 /* Now parse the line */
1186
1187 addr = gethex (4, buffer, &ok);
1188 idx = 6;
1189 for (p = 0; p < 16; p += 2)
1190 {
1191 byte[p] = gethex (2, buffer + idx, &ok);
1192 byte[p + 1] = gethex (2, buffer + idx + 2, &ok);
1193 idx += 5;
1194
1195 }
1196
1197 for (p = 0; p < 16; p++)
1198 {
1199 if (addr + p >= memaddr &&
1200 addr + p < memaddr + len)
1201 {
1202 myaddr[(addr + p) - memaddr] = byte[p];
1203
1204 }
1205
1206 }
fa4b55a1 1207 }
a493d9a6 1208 expect ("emory>");
ec25d19b
SC
1209 hms_write_cr (" ");
1210 expect_prompt ();
fa4b55a1 1211 return len;
fa4b55a1
SC
1212}
1213
1214/* This routine is run as a hook, just before the main command loop is
1215 entered. If gdb is configured for the H8, but has not had its
1216 target specified yet, this will loop prompting the user to do so.
1217*/
1218
1219hms_before_main_loop ()
1220{
1221 char ttyname[100];
1222 char *p, *p2;
199b2450 1223 extern GDB_FILE *instream;
fa4b55a1
SC
1224
1225 push_target (&hms_ops);
fa4b55a1
SC
1226}
1227
fa4b55a1 1228#define MAX_BREAKS 16
ec25d19b 1229static int num_brkpts = 0;
fa4b55a1 1230static int
ec25d19b
SC
1231hms_insert_breakpoint (addr, save)
1232 CORE_ADDR addr;
1233 char *save; /* Throw away, let hms save instructions */
fa4b55a1 1234{
ec25d19b
SC
1235 check_open ();
1236
1237 if (num_brkpts < MAX_BREAKS)
1238 {
1239 char buffer[100];
fa4b55a1 1240
ec25d19b
SC
1241 num_brkpts++;
1242 sprintf (buffer, "b %x", addr & 0xffff);
1243 hms_write_cr (buffer);
1244 expect_prompt ();
1245 return (0);
1246 }
1247 else
1248 {
199b2450 1249 fprintf_filtered (gdb_stderr,
ec25d19b
SC
1250 "Too many break points, break point not installed\n");
1251 return (1);
1252 }
fa4b55a1
SC
1253
1254}
1255static int
ec25d19b
SC
1256hms_remove_breakpoint (addr, save)
1257 CORE_ADDR addr;
1258 char *save; /* Throw away, let hms save instructions */
fa4b55a1 1259{
ec25d19b
SC
1260 if (num_brkpts > 0)
1261 {
1262 char buffer[100];
1263
1264 num_brkpts--;
1265 sprintf (buffer, "b - %x", addr & 0xffff);
1266 hms_write_cr (buffer);
1267 expect_prompt ();
1268
1269 }
1270 return (0);
fa4b55a1
SC
1271}
1272
1273/* Clear the hmss notion of what the break points are */
1274static int
ec25d19b
SC
1275hms_clear_breakpoints ()
1276{
fa4b55a1 1277
ec25d19b
SC
1278 if (is_open)
1279 {
1280 hms_write_cr ("b -");
1281 expect_prompt ();
1282 }
fa4b55a1 1283 num_brkpts = 0;
fa4b55a1
SC
1284}
1285static void
ec25d19b
SC
1286hms_mourn ()
1287{
1288 hms_clear_breakpoints ();
71607f9d 1289 unpush_target (&hms_ops);
fa4b55a1 1290 generic_mourn_inferior ();
fa4b55a1
SC
1291}
1292
fa4b55a1 1293/* Put a command string, in args, out to the hms. The hms is assumed to
ae0ea72e 1294 be in raw mode, all writing/reading done through desc.
fa4b55a1
SC
1295 Ouput from the hms is placed on the users terminal until the
1296 prompt from the hms is seen.
1297 FIXME: Can't handle commands that take input. */
1298
1299void
1300hms_com (args, fromtty)
ec25d19b
SC
1301 char *args;
1302 int fromtty;
fa4b55a1 1303{
ec25d19b
SC
1304 check_open ();
1305
1306 if (!args)
1307 return;
1308
fa4b55a1
SC
1309 /* Clear all input so only command relative output is displayed */
1310
ec25d19b
SC
1311 hms_write_cr (args);
1312 hms_write ("\030", 1);
1313 expect_prompt ();
fa4b55a1
SC
1314}
1315
1316/* Define the target subroutine names */
1317
ec25d19b
SC
1318struct target_ops hms_ops =
1319{
1320 "hms", "Remote HMS monitor",
1321 "Use the H8 evaluation board running the HMS monitor connected\n\
fa4b55a1
SC
1322by a serial line.",
1323
ec25d19b
SC
1324 hms_open, hms_close,
1325 0, hms_detach, hms_resume, hms_wait, /* attach */
1326 hms_fetch_register, hms_store_register,
1327 hms_prepare_to_store,
1328 hms_xfer_inferior_memory,
1329 hms_files_info,
1330 hms_insert_breakpoint, hms_remove_breakpoint, /* Breakpoints */
1331 0, 0, 0, 0, 0, /* Terminal handling */
1332 hms_kill, /* FIXME, kill */
1333 hms_load,
1334 0, /* lookup_symbol */
1335 hms_create_inferior, /* create_inferior */
1336 hms_mourn, /* mourn_inferior FIXME */
1337 0, /* can_run */
1338 0, /* notice_signals */
1339 process_stratum, 0, /* next */
1340 1, 1, 1, 1, 1, /* all mem, mem, stack, regs, exec */
1341 0, 0, /* Section pointers */
1342 OPS_MAGIC, /* Always the last thing */
fa4b55a1
SC
1343};
1344
ec25d19b 1345hms_quiet ()
fa4b55a1 1346{
ec25d19b
SC
1347 quiet = !quiet;
1348 if (quiet)
1349 printf_filtered ("Snoop disabled\n");
1350 else
1351 printf_filtered ("Snoop enabled\n");
ae0ea72e 1352
fa4b55a1
SC
1353}
1354
ec25d19b
SC
1355hms_device (s)
1356 char *s;
fa4b55a1 1357{
ec25d19b
SC
1358 if (s)
1359 {
1360 dev_name = get_word (&s);
1361 }
fa4b55a1
SC
1362}
1363
ec25d19b
SC
1364static
1365hms_speed (s)
1366 char *s;
fa4b55a1 1367{
ec25d19b
SC
1368 check_open ();
1369
1370 if (s)
1371 {
1372 char buffer[100];
1373 int newrate = atoi (s);
1374 int which = 0;
1375
a493d9a6 1376 if (SERIAL_SETBAUDRATE (desc, newrate))
ec25d19b
SC
1377 error ("Can't use %d baud\n", newrate);
1378
1379 printf_filtered ("Checking target is in sync\n");
1380
ec25d19b
SC
1381 printf_filtered ("Sending commands to set target to %d\n",
1382 baudrate);
1383
1384 sprintf (buffer, "tm %d. N 8 1", baudrate);
1385 hms_write_cr (buffer);
1386 }
fa4b55a1
SC
1387}
1388
1389/***********************************************************************/
1390
1391void
1392_initialize_remote_hms ()
1393{
1394 add_target (&hms_ops);
ec25d19b 1395
fa4b55a1 1396 add_com ("hms <command>", class_obscure, hms_com,
ec25d19b 1397 "Send a command to the HMS monitor.");
fa4b55a1
SC
1398 add_com ("snoop", class_obscure, hms_quiet,
1399 "Show what commands are going to the monitor");
ae0ea72e 1400
fa4b55a1
SC
1401 add_com ("device", class_obscure, hms_device,
1402 "Set the terminal line for HMS communications");
1403
1404 add_com ("speed", class_obscure, hms_speed,
1405 "Set the terminal line speed for HMS communications");
ec25d19b 1406
3ec5a74b 1407 dev_name = NULL;
fa4b55a1 1408}
This page took 0.197642 seconds and 4 git commands to generate.