* remote-sim.c: first attempt at general simulator interface
[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{
625
fa4b55a1 626 /* Clear any break points */
ec25d19b 627 hms_clear_breakpoints ();
fa4b55a1 628
ec25d19b
SC
629 /* Put this port back into REMOTE mode */
630 sleep (1); /* Let any output make it all the way back */
631 serial_write ("R\r", 2);
632 serial_close ();
ae0ea72e 633 is_open = 0;
fa4b55a1
SC
634}
635
fa4b55a1
SC
636/* Terminate the open connection to the remote debugger.
637 Use this when you want to detach and do something else
638 with your gdb. */
639void
ec25d19b 640hms_detach (args, from_tty)
fa4b55a1
SC
641 char *args;
642 int from_tty;
643{
ae0ea72e 644 if (is_open)
ec25d19b
SC
645 {
646 hms_clear_breakpoints ();
647 }
648
649 pop_target (); /* calls hms_close to do the real work */
fa4b55a1
SC
650 if (from_tty)
651 printf_filtered ("Ending remote %s debugging\n", target_shortname);
fa4b55a1 652}
ec25d19b 653
fa4b55a1
SC
654/* Tell the remote machine to resume. */
655
656void
657hms_resume (step, sig)
658 int step, sig;
659{
ec25d19b
SC
660 dcache_flush ();
661
662 if (step)
663 {
664 hms_write_cr ("s");
665 expect ("Step>");
666
667 /* Force the next hms_wait to return a trap. Not doing anything
fa4b55a1
SC
668 about I/O from the target means that the user has to type
669 "continue" to see any. FIXME, this should be fixed. */
ec25d19b
SC
670 need_artificial_trap = 1;
671 }
fa4b55a1 672 else
ec25d19b
SC
673 {
674 hms_write_cr ("g");
675 expect ("g");
676 }
fa4b55a1
SC
677}
678
679/* Wait until the remote machine stops, then return,
680 storing status in STATUS just as `wait' would. */
681
682int
683hms_wait (status)
684 WAITTYPE *status;
685{
ec25d19b 686 /* Strings to look for. '?' means match any single character.
fa4b55a1
SC
687 Note that with the algorithm we use, the initial character
688 of the string cannot recur in the string, or we will not
689 find some cases of the string in the input. */
ec25d19b 690
96743d3c 691 static char bpt[] = "At breakpoint:";
ec25d19b 692
fa4b55a1
SC
693 /* It would be tempting to look for "\n[__exit + 0x8]\n"
694 but that requires loading symbols with "yc i" and even if
695 we did do that we don't know that the file has symbols. */
696 static char exitmsg[] = "HMS>";
697 char *bp = bpt;
698 char *ep = exitmsg;
699
700 /* Large enough for either sizeof (bpt) or sizeof (exitmsg) chars. */
701 char swallowed[50];
ec25d19b 702
fa4b55a1
SC
703 /* Current position in swallowed. */
704 char *swallowed_p = swallowed;
705
706 int ch;
707 int ch_handled;
708 int old_timeout = timeout;
709 int old_immediate_quit = immediate_quit;
1f46923f 710 int swallowed_cr = 0;
ec25d19b 711
fa4b55a1
SC
712 WSETEXIT ((*status), 0);
713
714 if (need_artificial_trap != 0)
ec25d19b
SC
715 {
716 WSETSTOP ((*status), SIGTRAP);
717 need_artificial_trap--;
718 return 0;
719 }
fa4b55a1 720
ec25d19b 721 timeout = 99999; /* Don't time out -- user program is running. */
1f46923f 722 immediate_quit = 1; /* Helps ability to QUIT */
ec25d19b 723 while (1)
96743d3c 724 {
ec25d19b
SC
725 QUIT; /* Let user quit and leave process running */
726 ch_handled = 0;
727 ch = readchar ();
728 if (ch == *bp)
729 {
730 bp++;
731 if (*bp == '\0')
732 break;
733 ch_handled = 1;
734
735 *swallowed_p++ = ch;
736 }
737 else
738 {
739 bp = bpt;
740 }
741 if (ch == *ep || *ep == '?')
742 {
743 ep++;
744 if (*ep == '\0')
745 break;
746
747 if (!ch_handled)
748 *swallowed_p++ = ch;
749 ch_handled = 1;
750 }
751 else
752 {
753 ep = exitmsg;
754 }
755
756 if (!ch_handled)
757 {
758 char *p;
759
760 /* Print out any characters which have been swallowed. */
761 for (p = swallowed; p < swallowed_p; ++p)
762 putc (*p, stdout);
763 swallowed_p = swallowed;
764
765 if ((ch != '\r' && ch != '\n') || swallowed_cr > 10)
766 {
767 putc (ch, stdout);
768 swallowed_cr = 10;
769 }
770 swallowed_cr++;
771
772 }
96743d3c 773 }
ec25d19b 774 if (*bp == '\0')
96743d3c 775 {
ec25d19b
SC
776 WSETSTOP ((*status), SIGTRAP);
777 expect_prompt ();
778 }
779 else
96743d3c 780 {
ec25d19b 781 WSETEXIT ((*status), 0);
96743d3c 782 }
ec25d19b 783
fa4b55a1
SC
784 timeout = old_timeout;
785 immediate_quit = old_immediate_quit;
fa4b55a1
SC
786 return 0;
787}
788
789/* Return the name of register number REGNO
790 in the form input and output by hms.
791
792 Returns a pointer to a static buffer containing the answer. */
793static char *
794get_reg_name (regno)
795 int regno;
796{
ec25d19b
SC
797 static char *rn[NUM_REGS] = REGISTER_NAMES;
798
fa4b55a1 799 return rn[regno];
fa4b55a1
SC
800}
801
802/* Read the remote registers. */
ec25d19b
SC
803static int
804gethex (length, start, ok)
805 unsigned int length;
806 char *start;
807 int *ok;
fa4b55a1
SC
808{
809 int result = 0;
ec25d19b
SC
810
811 while (length--)
fa4b55a1 812 {
ec25d19b
SC
813 result <<= 4;
814 if (*start >= 'a' && *start <= 'f')
815 {
816 result += *start - 'a' + 10;
817 }
818 else if (*start >= 'A' && *start <= 'F')
819 {
820 result += *start - 'A' + 10;
821 }
822 else if (*start >= '0' && *start <= '9')
823 {
824 result += *start - '0';
825 }
826 else
827 *ok = 0;
828 start++;
829
fa4b55a1 830 }
fa4b55a1
SC
831 return result;
832}
ec25d19b
SC
833static int
834timed_read (buf, n, timeout)
835 char *buf;
fa4b55a1
SC
836
837{
838 int i;
839 char c;
ec25d19b 840
fa4b55a1 841 i = 0;
ec25d19b
SC
842 while (i < n)
843 {
844 c = readchar ();
845
846 if (c == 0)
847 return i;
848 buf[i] = c;
849 i++;
850
851 }
852 return i;
fa4b55a1
SC
853
854}
ec25d19b
SC
855
856hms_write (a, l)
857 char *a;
fa4b55a1
SC
858{
859 int i;
ec25d19b
SC
860
861 serial_write (a, l);
ae0ea72e 862
96743d3c 863 if (!quiet)
ec25d19b
SC
864 for (i = 0; i < l; i++)
865 {
866 printf ("%c", a[i]);
867 }
fa4b55a1
SC
868}
869
ec25d19b
SC
870hms_write_cr (s)
871 char *s;
fa4b55a1 872{
ec25d19b
SC
873 hms_write (s, strlen (s));
874 hms_write ("\r", 1);
1f46923f
SC
875}
876
877static void
ae0ea72e 878hms_fetch_register (dummy)
ec25d19b 879 int dummy;
fa4b55a1
SC
880{
881#define REGREPLY_SIZE 79
ec25d19b 882 char linebuf[REGREPLY_SIZE + 1];
fa4b55a1 883 int i;
ec25d19b 884 int s;
fa4b55a1 885 int gottok;
ec25d19b 886
1f46923f
SC
887 REGISTER_TYPE reg[NUM_REGS];
888 int foo[8];
ec25d19b
SC
889
890 check_open ();
891
892 do
fa4b55a1 893 {
ec25d19b
SC
894
895 hms_write_cr ("r");
896 s = timed_read (linebuf, REGREPLY_SIZE, 1);
897
898 linebuf[REGREPLY_SIZE] = 0;
899 gottok = 0;
900 if (linebuf[0] == 'r' &&
901 linebuf[3] == 'P' &&
902 linebuf[4] == 'C' &&
903 linebuf[5] == '=' &&
904 linebuf[75] == 'H' &&
905 linebuf[76] == 'M' &&
906 linebuf[77] == 'S')
907 {
908 /*
fa4b55a1
SC
909 PC=XXXX CCR=XX:XXXXXXXX R0-R7= XXXX XXXX XXXX XXXX XXXX XXXX XXXX XXXX
910 5436789012345678901234567890123456789012345678901234567890123456789012
ec25d19b 911 0 1 2 3 4 5 6
fa4b55a1 912 */
ec25d19b
SC
913 gottok = 1;
914
915 reg[PC_REGNUM] = gethex (4, linebuf + 6, &gottok);
916 reg[CCR_REGNUM] = gethex (2, linebuf + 15, &gottok);
917 for (i = 0; i < 8; i++)
918 {
919 reg[i] = gethex (4, linebuf + 34 + 5 * i, &gottok);
920 }
921 }
fa4b55a1 922 }
fa4b55a1 923 while (!gottok);
ec25d19b
SC
924 for (i = 0; i < NUM_REGS; i++)
925 {
926 char swapped[2];
fa4b55a1 927
ec25d19b
SC
928 swapped[1] = reg[i];
929 swapped[0] = (reg[i]) >> 8;
fa4b55a1 930
ec25d19b
SC
931 supply_register (i, swapped);
932 }
933}
fa4b55a1
SC
934
935/* Store register REGNO, or all if REGNO == -1.
936 Return errno value. */
ae0ea72e 937static void
fa4b55a1
SC
938hms_store_register (regno)
939 int regno;
940{
941
1f46923f 942 /* printf("hms_store_register() called.\n"); fflush(stdout); /* */
ec25d19b 943 if (regno == -1)
ae0ea72e 944 {
ec25d19b
SC
945 for (regno = 0; regno < NUM_REGS; regno++)
946 {
947 hms_store_register (regno);
948 }
ae0ea72e 949 }
fa4b55a1 950 else
ec25d19b
SC
951 {
952 char *name = get_reg_name (regno);
953 char buffer[100];
ae0ea72e 954
ec25d19b
SC
955 sprintf (buffer, "r %s=%x", name, read_register (regno));
956 hms_write_cr (buffer);
957 expect_prompt ();
958 }
959}
ae0ea72e 960
fa4b55a1
SC
961/* Get ready to modify the registers array. On machines which store
962 individual registers, this doesn't need to do anything. On machines
963 which store all the registers in one fell swoop, this makes sure
964 that registers contains all the registers from the program being
965 debugged. */
966
967void
968hms_prepare_to_store ()
969{
970 /* Do nothing, since we can store individual regs */
971}
972
ec25d19b
SC
973static CORE_ADDR
974translate_addr (addr)
975 CORE_ADDR addr;
fa4b55a1
SC
976{
977
ec25d19b 978 return (addr);
fa4b55a1
SC
979
980}
981
982/* Read a word from remote address ADDR and return it.
983 * This goes through the data cache.
984 */
985int
986hms_fetch_word (addr)
987 CORE_ADDR addr;
988{
ec25d19b 989 return dcache_fetch (addr);
fa4b55a1
SC
990}
991
992/* Write a word WORD into remote address ADDR.
993 This goes through the data cache. */
994
995void
996hms_store_word (addr, word)
997 CORE_ADDR addr;
998 int word;
999{
ec25d19b 1000 dcache_poke (addr, word);
fa4b55a1
SC
1001}
1002
1003int
ec25d19b 1004hms_xfer_inferior_memory (memaddr, myaddr, len, write, target)
fa4b55a1
SC
1005 CORE_ADDR memaddr;
1006 char *myaddr;
1007 int len;
1008 int write;
ec25d19b 1009 struct target_ops *target; /* ignored */
fa4b55a1
SC
1010{
1011 register int i;
ec25d19b 1012
fa4b55a1 1013 /* Round starting address down to longword boundary. */
ec25d19b
SC
1014 register CORE_ADDR addr;
1015
fa4b55a1
SC
1016 /* Round ending address up; get number of longwords that makes. */
1017 register int count;
ec25d19b 1018
fa4b55a1 1019 /* Allocate buffer of that many longwords. */
ec25d19b 1020 register int *buffer;
fa4b55a1
SC
1021
1022 memaddr &= 0xffff;
ec25d19b
SC
1023 addr = memaddr & -sizeof (int);
1024 count = (((memaddr + len) - addr) + sizeof (int) - 1) / sizeof (int);
fa4b55a1 1025
ec25d19b 1026 buffer = (int *) alloca (count * sizeof (int));
1f46923f 1027
fa4b55a1 1028 if (write)
ec25d19b
SC
1029 {
1030 /* Fill start and end extra bytes of buffer with existing memory data. */
fa4b55a1 1031
ec25d19b
SC
1032 if (addr != memaddr || len < (int) sizeof (int))
1033 {
1034 /* Need part of initial word -- fetch it. */
1035 buffer[0] = hms_fetch_word (addr);
1036 }
fa4b55a1 1037
ec25d19b
SC
1038 if (count > 1) /* FIXME, avoid if even boundary */
1039 {
1040 buffer[count - 1]
1041 = hms_fetch_word (addr + (count - 1) * sizeof (int));
1042 }
fa4b55a1 1043
ec25d19b 1044 /* Copy data to be written over corresponding part of buffer */
fa4b55a1 1045
ec25d19b 1046 bcopy (myaddr, (char *) buffer + (memaddr & (sizeof (int) - 1)), len);
fa4b55a1 1047
ec25d19b 1048 /* Write the entire buffer. */
fa4b55a1 1049
ec25d19b
SC
1050 for (i = 0; i < count; i++, addr += sizeof (int))
1051 {
1052 errno = 0;
1053 hms_store_word (addr, buffer[i]);
1054 if (errno)
1055 {
1056
1057 return 0;
1058 }
1059
1060 }
fa4b55a1 1061 }
fa4b55a1 1062 else
fa4b55a1 1063 {
ec25d19b
SC
1064 /* Read all the longwords */
1065 for (i = 0; i < count; i++, addr += sizeof (int))
1066 {
1067 errno = 0;
1068 buffer[i] = hms_fetch_word (addr);
1069 if (errno)
1070 {
1071 return 0;
1072 }
1073 QUIT;
1074 }
fa4b55a1 1075
ec25d19b
SC
1076 /* Copy appropriate bytes out of the buffer. */
1077 bcopy ((char *) buffer + (memaddr & (sizeof (int) - 1)), myaddr, len);
1078 }
fa4b55a1 1079
fa4b55a1
SC
1080 return len;
1081}
1082
fa4b55a1
SC
1083int
1084hms_write_inferior_memory (memaddr, myaddr, len)
1085 CORE_ADDR memaddr;
ae0ea72e 1086 unsigned char *myaddr;
fa4b55a1
SC
1087 int len;
1088{
ae0ea72e
SC
1089 bfd_vma addr;
1090 int done;
ec25d19b
SC
1091 int todo;
1092
ae0ea72e 1093 done = 0;
ec25d19b 1094 while (done < len)
ae0ea72e 1095 {
ec25d19b
SC
1096 char buffer[20];
1097 int thisgo;
1098 int idx;
1099
1100 thisgo = len - done;
1101 if (thisgo > 20)
1102 thisgo = 20;
ae0ea72e 1103
ec25d19b
SC
1104 sprintf (buffer, "M.B %4x =", memaddr + done);
1105 hms_write (buffer, 10);
1106 for (idx = 0; idx < thisgo; idx++)
1107 {
1108 char buf[20];
1109
1110 sprintf (buf, "%2x ", myaddr[idx + done]);
1111 hms_write (buf, 3);
1112 }
1113 hms_write_cr ("");
1114 expect_prompt ();
1115 done += thisgo;
1116 }
fa4b55a1 1117
fa4b55a1
SC
1118}
1119
1120void
1121hms_files_info ()
1122{
ec25d19b
SC
1123 char *file = "nothing";
1124
1125 if (exec_bfd)
1126 file = bfd_get_filename (exec_bfd);
ae0ea72e 1127
ec25d19b 1128 if (exec_bfd)
ae0ea72e 1129#ifdef __GO32__
ec25d19b 1130 printf_filtered ("\tAttached to DOS asynctsr and running program %s\n", file);
ae0ea72e 1131#else
ec25d19b 1132 printf_filtered ("\tAttached to %s at %d baud and running program %s\n", file);
ae0ea72e 1133#endif
ec25d19b 1134 printf_filtered ("\ton an H8/300 processor.\n");
fa4b55a1
SC
1135}
1136
1137/* Copy LEN bytes of data from debugger memory at MYADDR
ec25d19b
SC
1138 to inferior's memory at MEMADDR. Returns errno value.
1139 * sb/sh instructions don't work on unaligned addresses, when TU=1.
fa4b55a1
SC
1140 */
1141
fa4b55a1
SC
1142/* Read LEN bytes from inferior memory at MEMADDR. Put the result
1143 at debugger address MYADDR. Returns errno value. */
1144int
ec25d19b 1145hms_read_inferior_memory (memaddr, myaddr, len)
fa4b55a1
SC
1146 CORE_ADDR memaddr;
1147 char *myaddr;
1148 int len;
1149{
1150 /* Align to nearest low 16 bits */
1151 int i;
ec25d19b 1152
fa4b55a1
SC
1153#if 0
1154 CORE_ADDR start = memaddr & ~0xf;
ec25d19b
SC
1155 CORE_ADDR end = ((memaddr + len + 16) & ~0xf) - 1;
1156
fa4b55a1
SC
1157#endif
1158 CORE_ADDR start = memaddr;
ec25d19b
SC
1159 CORE_ADDR end = memaddr + len - 1;
1160
1161 int ok = 1;
1162
fa4b55a1
SC
1163 /*
1164 AAAA: XXXX XXXX XXXX XXXX XXXX XXXX XXXX XXXX '................'
1165 012345678901234567890123456789012345678901234567890123456789012345
1166 0 1 2 3 4 5 6
1167 */
1168 char buffer[66];
ec25d19b
SC
1169
1170 if (memaddr & 0xf)
1171 abort ();
1172 if (len != 16)
1173 abort ();
1174
1175 sprintf (buffer, "m %4x %4x", start & 0xffff, end & 0xffff);
1176 hms_write_cr (buffer);
fa4b55a1
SC
1177 /* drop the echo and newline*/
1178 for (i = 0; i < 13; i++)
ec25d19b 1179 readchar ();
fa4b55a1 1180
fa4b55a1
SC
1181 /* Grab the lines as they come out and fill the area */
1182 /* Skip over cr */
ec25d19b 1183 while (1)
fa4b55a1 1184 {
ec25d19b
SC
1185 int p;
1186 int i;
1187 int addr;
1188 size_t idx;
fa4b55a1 1189
ec25d19b
SC
1190 char byte[16];
1191
1192 buffer[0] = readchar ();
1193 if (buffer[0] == 'M')
1194 break;
1195 for (i = 1; i < 66; i++)
1196 buffer[i] = readchar ();
1197
1198 /* Now parse the line */
1199
1200 addr = gethex (4, buffer, &ok);
1201 idx = 6;
1202 for (p = 0; p < 16; p += 2)
1203 {
1204 byte[p] = gethex (2, buffer + idx, &ok);
1205 byte[p + 1] = gethex (2, buffer + idx + 2, &ok);
1206 idx += 5;
1207
1208 }
1209
1210 for (p = 0; p < 16; p++)
1211 {
1212 if (addr + p >= memaddr &&
1213 addr + p < memaddr + len)
1214 {
1215 myaddr[(addr + p) - memaddr] = byte[p];
1216
1217 }
1218
1219 }
fa4b55a1 1220 }
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.117854 seconds and 4 git commands to generate.