]> git.ipfire.org Git - thirdparty/binutils-gdb.git/blob - gdb/remote-udi.c
NOTICE_SIGNAL_HANDLING_CHANGE macro added to the target vector as
[thirdparty/binutils-gdb.git] / gdb / remote-udi.c
1 /* Remote debugging interface for AMD 29k interfaced via UDI, for GDB.
2 Copyright 1990, 1992 Free Software Foundation, Inc.
3 Written by Daniel Mann. Contributed by AMD.
4
5 This file is part of GDB.
6
7 This program is free software; you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation; either version 2 of the License, or
10 (at your option) any later version.
11
12 This program is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 GNU General Public License for more details.
16
17 You should have received a copy of the GNU General Public License
18 along with this program; if not, write to the Free Software
19 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
20
21 /* This is like remote.c but uses the Universal Debug Interface (UDI) to
22 talk to the target hardware (or simulator). UDI is a TCP/IP based
23 protocol; for hardware that doesn't run TCP, an interface adapter
24 daemon talks UDI on one side, and talks to the hardware (typically
25 over a serial port) on the other side.
26
27 - Originally written by Daniel Mann at AMD for MiniMON and gdb 3.91.6.
28 - David Wood (wood@lab.ultra.nyu.edu) at New York University adapted this
29 file to gdb 3.95. I was unable to get this working on sun3os4
30 with termio, only with sgtty. Because we are only attempting to
31 use this module to debug our kernel, which is already loaded when
32 gdb is started up, I did not code up the file downloading facilities.
33 As a result this module has only the stubs to download files.
34 You should get tagged at compile time if you need to make any
35 changes/additions.
36 - Daniel Mann at AMD took the 3.95 adaptions above and replaced
37 MiniMON interface with UDI-p interface. */
38
39 #include "defs.h"
40 #include "inferior.h"
41 #include "wait.h"
42 #include "value.h"
43 #include <ctype.h>
44 #include <fcntl.h>
45 #include <signal.h>
46 #include <errno.h>
47 #include <string.h>
48 #include "terminal.h"
49 #include "target.h"
50 #include "29k-share/udi/udiproc.h"
51 #include "gdbcmd.h"
52
53 /* access the register store directly, without going through
54 the normal handler functions. This avoids an extra data copy. */
55
56 static int kiodebug;
57 extern int stop_soon_quietly; /* for wait_for_inferior */
58 extern struct value *call_function_by_hand();
59 static void udi_resume();
60 static void udi_fetch_registers ();
61 static void udi_load();
62 static void fetch_register ();
63 static void udi_store_registers ();
64 static int store_register ();
65 static int regnum_to_srnum();
66 static void udi_close ();
67 static CPUSpace udi_memory_space();
68 static int udi_write_inferior_memory();
69 static int udi_read_inferior_memory();
70 char CoffFileName[100] = "";
71 /*
72 * Processor types.
73 */
74 #define TYPE_UNKNOWN 0
75 #define TYPE_A29000 1
76 #define TYPE_A29030 2
77 #define TYPE_A29050 3
78 static char *processor_name[] = { "Unknown", "Am29000", "Am29030", "Am29050" };
79 static int processor_type=TYPE_UNKNOWN;
80 #define FREEZE_MODE (read_register(CPS_REGNUM) && 0x400)
81 #define USE_SHADOW_PC ((processor_type == TYPE_A29050) && FREEZE_MODE)
82
83 #define LLOG_FILE "udi.log"
84 #if defined (LOG_FILE)
85 FILE *log_file;
86 #endif
87
88 static int timeout = 5;
89 extern struct target_ops udi_ops; /* Forward declaration */
90
91 /* Special register enumeration.
92 */
93
94 /******************************************************************* UDI DATA*/
95 #define MAXDATA 2*1024 /* max UDI[read/write] byte size */
96 /* Descriptor for I/O to remote machine. Initialize it to -1 so that
97 udi_open knows that we don't have a file open when the program
98 starts. */
99 UDISessionId udi_session_id = -1;
100
101 CPUOffset IMemStart = 0;
102 CPUSizeT IMemSize = 0;
103 CPUOffset DMemStart = 0;
104 CPUSizeT DMemSize = 0;
105 CPUOffset RMemStart = 0;
106 CPUSizeT RMemSize = 0;
107 UDIUInt32 CPUPRL;
108 UDIUInt32 CoProcPRL;
109
110 #define SBUF_MAX 1024 /* maximum size of string handling buffer */
111 char sbuf[SBUF_MAX];
112
113 typedef struct bkpt_entry_str
114 {
115 UDIResource Addr;
116 UDIUInt32 PassCount;
117 UDIBreakType Type;
118 unsigned int BreakId;
119 } bkpt_entry_t;
120 #define BKPT_TABLE_SIZE 40
121 static bkpt_entry_t bkpt_table[BKPT_TABLE_SIZE];
122 extern char dfe_errmsg[]; /* error string */
123
124 /*********************************************************** SIGNAL SUPPORT */
125 /* Called when SIGALRM signal sent due to alarm() timeout. */
126 #ifndef HAVE_TERMIO
127
128 #ifndef __STDC__
129 # ifndef volatile
130 # define volatile /**/
131 # endif
132 #endif
133 volatile int n_alarms;
134
135 static void
136 udi_timer ()
137 {
138 #if 0
139 if (kiodebug)
140 printf ("udi_timer called\n");
141 #endif
142 n_alarms++;
143 }
144 #endif /* HAVE_TERMIO */
145
146 /* malloc'd name of the program on the remote system. */
147 static char *prog_name = NULL;
148
149
150 /* Number of SIGTRAPs we need to simulate. That is, the next
151 NEED_ARTIFICIAL_TRAP calls to udi_wait should just return
152 SIGTRAP without actually waiting for anything. */
153
154 /******************************************************* UDI_CREATE_INFERIOR */
155 /* This is called not only when we first attach, but also when the
156 user types "run" after having attached. */
157 static void
158 udi_create_inferior (execfile, args, env)
159 char *execfile;
160 char *args;
161 char **env;
162 {
163
164 if (execfile)
165 { if (prog_name != NULL)
166 free (prog_name);
167 prog_name = savestring (execfile, strlen (execfile));
168 }
169
170 if (prog_name == 0 /* || exec_bfd == 0 */ )
171 error ("No exec file specified");
172
173 if (udi_session_id < 0){
174 printf("UDI connection not open yet.\n");
175 return;
176 }
177
178 inferior_pid = 40000;
179
180 #if defined(ULTRA3) && defined(KERNEL_DEBUGGING)
181 /* On ultra3 (NYU) we assume the kernel is already running so there is
182 * no file to download
183 */
184 #else
185 udi_load(args, 0);
186 #endif /* !ULTRA3 */
187
188 init_wait_for_inferior ();
189 clear_proceed_status ();
190 proceed(-1,-1,0);
191 }
192 /******************************************************* UDI_MOURN_INFERIOR */
193 static void
194 udi_mourn()
195 {
196 pop_target (); /* Pop back to no-child state */
197 generic_mourn_inferior ();
198 }
199
200 /******************************************************************** UDI_OPEN
201 ** Open a connection to remote TIP.
202 NAME is the socket domain used for communication with the TIP,
203 then a space and the socket name or TIP-host name.
204 '<udi_udi_config_id> [progname]' for example.
205 */
206
207 /* XXX - need cleanups for udiconnect for various failures!!! */
208
209 static char *udi_config_id;
210 static void
211 udi_open (name, from_tty)
212 char *name;
213 int from_tty;
214 {
215 unsigned int prl;
216 char *p;
217 int cnt;
218 UDIMemoryRange KnownMemory[10];
219 UDIUInt32 ChipVersions[10];
220 UDIInt NumberOfRanges = 10;
221 UDIInt NumberOfChips = 10;
222 UDIPId PId;
223 UDIUInt32 TIPId, TargetId, DFEId, DFE, TIP, DFEIPCId, TIPIPCId;
224
225 target_preopen(from_tty);
226
227 /* Find the first whitespace character, it separates udi_config_id
228 from prog_name. */
229 if(!name) goto erroid;
230 for (p = name;
231 *p != '\0' && !isspace (*p); p++)
232 ;
233 if (*p == '\0')
234 erroid:
235 error("Usage: target udi config_id progname, where config_id appears in udi_soc file");
236
237 udi_config_id = (char*)malloc (p - name + 1);
238 strncpy (udi_config_id, name, p - name);
239 udi_config_id[p - name] = '\0';
240
241 /* Skip over the whitespace after udi_config_id */
242 for (; isspace (*p); p++)
243 /*EMPTY*/;
244
245 if (prog_name != NULL)
246 free (prog_name);
247 prog_name = savestring (p, strlen (p));
248
249 if (UDIConnect(udi_config_id, &udi_session_id))
250 error("UDIConnect() failed: %s\n", dfe_errmsg);
251
252 push_target (&udi_ops);
253
254 #ifndef HAVE_TERMIO
255 #ifndef NO_SIGINTERRUPT
256 /* Cause SIGALRM's to make reads fail with EINTR instead of resuming
257 the read. */
258 if (siginterrupt (SIGALRM, 1) != 0)
259 error ("udi_open: siginterrupt() %s", safe_strerror(errno));
260 #endif
261
262 /* Set up read timeout timer. */
263 if ((void (*)) signal (SIGALRM, udi_timer) == (void (*)) -1)
264 error ("udi_open: signal() %s", safe_strerror(errno));
265 #endif
266
267 #if defined (LOG_FILE)
268 log_file = fopen (LOG_FILE, "w");
269 if (log_file == NULL)
270 error ("udi_open: fopen(%s) %s", LOG_FILE, safe_strerror(errno));
271 #endif
272 /*
273 ** Initialize target configuration structure (global)
274 */
275 if(UDIGetTargetConfig( KnownMemory, &NumberOfRanges,
276 ChipVersions, &NumberOfChips))
277 error ("UDIGetTargetConfig() failed");
278 if(NumberOfChips > 2)
279 fprintf(stderr,"Taret has more than one processor\n");
280 for(cnt=0; cnt<NumberOfRanges; cnt++)
281 { switch(KnownMemory[cnt].Space)
282 {
283 default: fprintf(stderr, "UDIGetTargetConfig() unknown memory space\n");
284 break;
285 case UDI29KCP_S:
286 break;
287 case UDI29KIROMSpace:
288 RMemStart = KnownMemory[cnt].Offset;
289 RMemSize = KnownMemory[cnt].Size;
290 break;
291 case UDI29KIRAMSpace:
292 IMemStart = KnownMemory[cnt].Offset;
293 IMemSize = KnownMemory[cnt].Size;
294 break;
295 case UDI29KDRAMSpace:
296 DMemStart = KnownMemory[cnt].Offset;
297 DMemSize = KnownMemory[cnt].Size;
298 break;
299 }
300 }
301
302 /* Determine the processor revision level */
303 prl = (unsigned int)read_register(CFG_REGNUM) >> 24;
304 if ((prl&0xe0) == 0)
305 { fprintf_filtered(stderr,
306 "Remote debugging Am29000 rev %c\n",'A'+(prl&0x1f));
307 processor_type = TYPE_A29000;
308 } else if ((prl&0xe0) == 0x40) /* 29030 = 0x4* */
309 { fprintf_filtered(stderr,
310 "Remote debugging Am2903* rev %c\n",'A'+(prl&0x1f));
311 processor_type = TYPE_A29030;
312 } else if ((prl&0xe0) == 0x20) /* 29050 = 0x2* */
313 { fprintf_filtered(stderr,
314 "Remote debugging Am29050 rev %c\n",'A'+(prl&0x1f));
315 processor_type = TYPE_A29050;
316 } else {
317 processor_type = TYPE_UNKNOWN;
318 fprintf_filtered(stderr,"WARNING: processor type unknown.\n");
319 }
320 if(UDICreateProcess(&PId))
321 fprintf(stderr, "UDICreateProcess() failed\n");
322
323 /* Print out some stuff, letting the user now what's going on */
324 if(UDICapabilities( &TIPId, &TargetId, DFEId, DFE, &TIP, &DFEIPCId,
325 &TIPIPCId, sbuf))
326 error ("UDICapabilities() failed");
327 if (from_tty) {
328 printf_filtered("Remote debugging an %s connected via UDI socket,\n\
329 DFE-IPC version %x.%x.%x TIP-IPC version %x.%x.%x TIP version %x.%x.%x\n %s\n",
330 processor_name[processor_type],
331 (DFEIPCId>>8)&0xf, (DFEIPCId>>4)&0xf, DFEIPCId&0xf,
332 (TIPIPCId>>8)&0xf, (TIPIPCId>>4)&0xf, TIPIPCId&0xf,
333 (TargetId>>8)&0xf, (TargetId>>4)&0xf, TargetId&0xf,
334 sbuf);
335 #ifdef ULTRA3
336 /* FIXME: can this restriction be removed? */
337 printf_filtered("Remote debugging using virtual addresses works only\n");
338 printf_filtered(" when virtual addresses map 1:1 to physical addresses.\n");
339 #endif
340 }
341 #ifdef ULTRA3
342 if (processor_type != TYPE_A29050) {
343 fprintf_filtered(stderr,
344 "Freeze-mode debugging can only be done on an Am29050,\n");
345 fprintf_filtered(stderr,
346 " unless GDB is being used with a 29K simulator.\n");
347 }
348 #endif
349 }
350
351 /******************************************************************* UDI_CLOSE
352 Close the open connection to the TIP process.
353 Use this when you want to detach and do something else
354 with your gdb. */
355 static void
356 udi_close (quitting) /*FIXME: how is quitting used */
357 int quitting;
358 {
359 int Terminate = -1;
360
361 if (udi_session_id < 0)
362 error ("Can't close udi connection: not debugging remotely.");
363
364 /* We should never get here if there isn't something valid in
365 udi_session_id.
366
367 if(UDIDisconnect(udi_stream, Terminate);)
368 error ("UDIDisconnect() failed in udi_close");
369
370 /* Do not try to close udi_session_id again, later in the program. */
371 udi_session_id = -1;
372 inferior_pid = 0;
373
374 #if defined (LOG_FILE)
375 if (ferror (log_file))
376 printf ("Error writing log file.\n");
377 if (fclose (log_file) != 0)
378 printf ("Error closing log file.\n");
379 #endif
380
381 printf_filtered (" Ending remote debugging\n");
382 }
383
384 /**************************************************************** UDI_ATACH */
385 /* Attach to a program that is already loaded and running
386 * Upon exiting the process's execution is stopped.
387 */
388 static void
389 udi_attach (args, from_tty)
390 char *args;
391 int from_tty;
392 {
393 UDIResource From;
394 UDIInt32 PC_adds;
395 UDICount Count = 1;
396 UDISizeT Size = 4;
397 UDICount CountDone;
398 UDIBool HostEndian = 0;
399
400 if (udi_session_id < 0)
401 error ("UDI connection not opened yet, use the 'target udi' command.\n");
402
403 if (from_tty)
404 printf ("Attaching to remote program %s...\n", prog_name);
405
406 UDIStop();
407 From.Space = 11;
408 From.Offset = UDI29KSpecialRegs;
409 if(UDIRead(From, &PC_adds, Count, Size, &CountDone, HostEndian))
410 error ("UDIRead failed in udi_attach");
411 printf ("Remote process is now halted, pc1 = 0x%x.\n", PC_adds);
412 }
413 /************************************************************* UDI_DETACH */
414 /* Terminate the open connection to the TIP process.
415 Use this when you want to detach and do something else
416 with your gdb. Leave remote process running (with no breakpoints set). */
417 static void
418 udi_detach (args,from_tty)
419 char *args;
420 int from_tty;
421 {
422 remove_breakpoints(); /* Just in case there were any left in */
423 if(UDIDisconnect(udi_session_id))
424 error ("UDIDisconnect() failed in udi_detach");
425 pop_target(); /* calls udi_close to do the real work */
426 if (from_tty)
427 printf ("Ending remote debugging\n");
428 }
429
430
431 /****************************************************************** UDI_RESUME
432 ** Tell the remote machine to resume. */
433
434 static void
435 udi_resume (step, sig)
436 int step, sig;
437 {
438 UDIError tip_error;
439 UDIUInt32 Steps = 1;
440 UDIStepType StepType = UDIStepNatural;
441 UDIRange Range;
442
443 if (step) /* step 1 instruction */
444 {
445 tip_error = UDIStep (Steps, StepType, Range);
446 if (!tip_error)
447 return;
448
449 fprintf (stderr, "UDIStep() error = %d\n", tip_error);
450 error ("failed in udi_resume");
451 }
452
453 if (UDIExecute())
454 error ("UDIExecute() failed in udi_resume");
455 }
456
457 /******************************************************************** UDI_WAIT
458 ** Wait until the remote machine stops, then return,
459 storing status in STATUS just as `wait' would. */
460
461 static int
462 udi_wait (status)
463 WAITTYPE *status;
464 {
465 UDIInt32 MaxTime;
466 UDIPId PId;
467 UDIInt32 StopReason;
468 UDISizeT CountDone;
469 int old_timeout = timeout;
470 int old_immediate_quit = immediate_quit;
471 int i;
472
473 WSETEXIT ((*status), 0);
474
475 /* wait for message to arrive. It should be:
476 If the target stops executing, udi_wait() should return.
477 */
478 timeout = 0; /* Wait indefinetly for a message */
479 immediate_quit = 1; /* Helps ability to QUIT */
480
481 while(1)
482 {
483 i = 0;
484 MaxTime = UDIWaitForever;
485 UDIWait(MaxTime, &PId, &StopReason);
486 QUIT; /* Let user quit if they want */
487
488 switch (StopReason & UDIGrossState)
489 {
490 case UDIStdoutReady:
491 if (UDIGetStdout (sbuf, (UDISizeT)SBUF_MAX, &CountDone))
492 error ("UDIGetStdin() failed in udi_wait");
493 fwrite (sbuf, 1, CountDone, stdout);
494 fflush(stdout);
495 continue;
496 case UDIStderrReady:
497 UDIGetStderr (sbuf, (UDISizeT)SBUF_MAX, &CountDone);
498 fwrite (sbuf, 1, CountDone, stderr);
499 fflush(stderr);
500 continue;
501 case UDIStdinNeeded:
502 printf("DEBUG: stdin requested ... continue\n");
503 /* UDIPutStdin(sbuf, (UDISizeT)i, &CountDone); */
504 continue;
505 case UDIStdinModeX:
506 continue;
507 default:
508 break;
509 }
510 break;
511 }
512
513 switch (StopReason & UDIGrossState)
514 {
515 case UDITrapped:
516 printf("Am290*0 received vector number %d\n", StopReason >> 24);
517
518 switch (StopReason >> 8)
519 {
520 case 0: /* Illegal opcode */
521 printf(" (break point)\n");
522 WSETSTOP ((*status), SIGTRAP);
523 break;
524 case 1: /* Unaligned Access */
525 WSETSTOP ((*status), SIGBUS);
526 break;
527 case 3:
528 case 4:
529 WSETSTOP ((*status), SIGFPE);
530 break;
531 case 5: /* Protection Violation */
532 WSETSTOP ((*status), SIGILL);
533 break;
534 case 6:
535 case 7:
536 case 8: /* User Instruction Mapping Miss */
537 case 9: /* User Data Mapping Miss */
538 case 10: /* Supervisor Instruction Mapping Miss */
539 case 11: /* Supervisor Data Mapping Miss */
540 WSETSTOP ((*status), SIGSEGV);
541 break;
542 case 12:
543 case 13:
544 WSETSTOP ((*status), SIGILL);
545 break;
546 case 14: /* Timer */
547 WSETSTOP ((*status), SIGALRM);
548 break;
549 case 15: /* Trace */
550 WSETSTOP ((*status), SIGTRAP);
551 break;
552 case 16: /* INTR0 */
553 case 17: /* INTR1 */
554 case 18: /* INTR2 */
555 case 19: /* INTR3/Internal */
556 case 20: /* TRAP0 */
557 case 21: /* TRAP1 */
558 WSETSTOP ((*status), SIGINT);
559 break;
560 case 22: /* Floating-Point Exception */
561 WSETSTOP ((*status), SIGILL);
562 break;
563 case 77: /* assert 77 */
564 WSETSTOP ((*status), SIGTRAP);
565 break;
566 default:
567 WSETEXIT ((*status), 0);
568 }
569 break;
570 case UDINotExecuting:
571 WSETSTOP ((*status), SIGTERM);
572 break;
573 case UDIRunning:
574 WSETSTOP ((*status), SIGILL);
575 break;
576 case UDIStopped:
577 WSETSTOP ((*status), SIGTSTP);
578 break;
579 case UDIWarned:
580 WSETSTOP ((*status), SIGLOST);
581 break;
582 case UDIStepped:
583 case UDIBreak:
584 WSETSTOP ((*status), SIGTRAP);
585 break;
586 case UDIWaiting:
587 WSETSTOP ((*status), SIGSTOP);
588 break;
589 case UDIHalted:
590 WSETSTOP ((*status), SIGKILL);
591 break;
592 case UDIExited:
593 default:
594 WSETEXIT ((*status), 0);
595 }
596
597 timeout = old_timeout; /* Restore original timeout value */
598 immediate_quit = old_immediate_quit;
599 return 0;
600 }
601
602 /********************************************************** UDI_FETCH_REGISTERS
603 * Read a remote register 'regno'.
604 * If regno==-1 then read all the registers.
605 */
606 static void
607 udi_fetch_registers (regno)
608 int regno;
609 {
610 UDIResource From;
611 UDIUInt32 *To;
612 UDICount Count;
613 UDISizeT Size = 4;
614 UDICount CountDone;
615 UDIBool HostEndian = 0;
616 int i;
617
618 if (regno >= 0) {
619 fetch_register(regno);
620 return;
621 }
622
623 /* Gr1/rsp */
624
625 From.Space = UDI29KGlobalRegs;
626 From.Offset = 1;
627 To = (UDIUInt32 *)&registers[4 * GR1_REGNUM];
628 Count = 1;
629 if (UDIRead(From, To, Count, Size, &CountDone, HostEndian))
630 error("UDIRead() failed in udi_fetch_registers");
631
632 register_valid[GR1_REGNUM] = 1;
633
634 #if defined(GR64_REGNUM) /* Read gr64-127 */
635
636 /* Global Registers gr64-gr95 */
637
638 From.Space = UDI29KGlobalRegs;
639 From.Offset = 64;
640 To = (UDIUInt32 *)&registers[4 * GR64_REGNUM];
641 Count = 32;
642 if (UDIRead(From, To, Count, Size, &CountDone, HostEndian))
643 error("UDIRead() failed in udi_fetch_registers");
644
645 for (i = GR64_REGNUM; i < GR64_REGNUM + 32; i++)
646 register_valid[i] = 1;
647
648 #endif /* GR64_REGNUM */
649
650 /* Global Registers gr96-gr127 */
651
652 From.Space = UDI29KGlobalRegs;
653 From.Offset = 96;
654 To = (UDIUInt32 *)&registers[4 * GR96_REGNUM];
655 Count = 32;
656 if (UDIRead(From, To, Count, Size, &CountDone, HostEndian))
657 error("UDIRead() failed in udi_fetch_registers");
658
659 for (i = GR96_REGNUM; i < GR96_REGNUM + 32; i++)
660 register_valid[i] = 1;
661
662 /* Local Registers */
663
664 From.Space = UDI29KLocalRegs;
665 From.Offset = 0;
666 To = (UDIUInt32 *)&registers[4 * LR0_REGNUM];
667 Count = 128;
668 if (UDIRead(From, To, Count, Size, &CountDone, HostEndian))
669 error("UDIRead() failed in udi_fetch_registers");
670
671 for (i = LR0_REGNUM; i < LR0_REGNUM + 128; i++)
672 register_valid[i] = 1;
673
674 /* Protected Special Registers */
675
676 From.Space = UDI29KSpecialRegs;
677 From.Offset = 0;
678 To = (UDIUInt32 *)&registers[4 * SR_REGNUM(0)];
679 Count = 15;
680 if (UDIRead(From, To, Count, Size, &CountDone, HostEndian))
681 error("UDIRead() failed in udi_fetch_registers");
682
683 for (i = SR_REGNUM(0); i < SR_REGNUM(0) + 15; i++)
684 register_valid[i] = 1;
685
686 if (USE_SHADOW_PC) { /* Let regno_to_srnum() handle the register number */
687 fetch_register(NPC_REGNUM);
688 fetch_register(PC_REGNUM);
689 fetch_register(PC2_REGNUM);
690
691 /* Unprotected Special Registers sr128-sr135 */
692
693 From.Space = UDI29KSpecialRegs;
694 From.Offset = 128;
695 To = (UDIUInt32 *)&registers[4 * SR_REGNUM(128)];
696 Count = 135-128 + 1;
697 if (UDIRead(From, To, Count, Size, &CountDone, HostEndian))
698 error("UDIRead() failed in udi_fetch_registers");
699
700 for (i = SR_REGNUM(128); i < SR_REGNUM(128) + 135-128+1; i++)
701 register_valid[i] = 1;
702 }
703
704 if (kiodebug)
705 {
706 printf("Fetching all registers\n");
707 printf("Fetching PC0 = 0x%x, PC1 = 0x%x, PC2 = 0x%x\n",
708 read_register(NPC_REGNUM), read_register(PC_REGNUM),
709 read_register(PC2_REGNUM));
710 }
711
712 /* There doesn't seem to be any way to get these. */
713 {
714 int val = -1;
715 supply_register (FPE_REGNUM, (char *) &val);
716 supply_register (INTE_REGNUM, (char *) &val);
717 supply_register (FPS_REGNUM, (char *) &val);
718 supply_register (EXO_REGNUM, (char *) &val);
719 }
720 }
721
722
723 /********************************************************* UDI_STORE_REGISTERS
724 ** Store register regno into the target.
725 * If regno==-1 then store all the registers.
726 */
727
728 static void
729 udi_store_registers (regno)
730 int regno;
731 {
732 UDIUInt32 *From;
733 UDIResource To;
734 UDICount Count;
735 UDISizeT Size = 4;
736 UDICount CountDone;
737 UDIBool HostEndian = 0;
738
739 if (regno >= 0)
740 {
741 store_register(regno);
742 return;
743 }
744
745 if (kiodebug)
746 {
747 printf("Storing all registers\n");
748 printf("PC0 = 0x%x, PC1 = 0x%x, PC2 = 0x%x\n", read_register(NPC_REGNUM),
749 read_register(PC_REGNUM), read_register(PC2_REGNUM));
750 }
751
752 /* Gr1/rsp */
753
754 From = (UDIUInt32 *)&registers[4 * GR1_REGNUM];
755 To.Space = UDI29KGlobalRegs;
756 To.Offset = 1;
757 Count = 1;
758 if(UDIWrite(From, To, Count, Size, &CountDone, HostEndian))
759 error("UDIWrite() failed in udi_store_regisetrs");
760
761 #if defined(GR64_REGNUM)
762
763 /* Global registers gr64-gr95 */
764
765 From = (UDIUInt32 *)&registers[4 * GR64_REGNUM];
766 To.Space = UDI29KGlobalRegs;
767 To.Offset = 64;
768 Count = 32;
769 if(UDIWrite(From, To, Count, Size, &CountDone, HostEndian))
770 error("UDIWrite() failed in udi_store_regisetrs");
771
772 #endif /* GR64_REGNUM */
773
774 /* Global registers gr96-gr127 */
775
776 From = (UDIUInt32 *)&registers[4 * GR96_REGNUM];
777 To.Space = UDI29KGlobalRegs;
778 To.Offset = 96;
779 Count = 32;
780 if(UDIWrite(From, To, Count, Size, &CountDone, HostEndian))
781 error("UDIWrite() failed in udi_store_regisetrs");
782
783 /* Local Registers */
784
785 From = (UDIUInt32 *)&registers[4 * LR0_REGNUM];
786 To.Space = UDI29KLocalRegs;
787 To.Offset = 0;
788 Count = 128;
789 if(UDIWrite(From, To, Count, Size, &CountDone, HostEndian))
790 error("UDIWrite() failed in udi_store_regisetrs");
791
792
793 /* Protected Special Registers */ /* VAB through TMR */
794
795 From = (UDIUInt32 *)&registers[4 * SR_REGNUM(0)];
796 To.Space = UDI29KSpecialRegs;
797 To.Offset = 0;
798 Count = 10;
799 if(UDIWrite(From, To, Count, Size, &CountDone, HostEndian))
800 error("UDIWrite() failed in udi_store_regisetrs");
801
802 /* PC0, PC1, PC2 possibly as shadow registers */
803
804 From = (UDIUInt32 *)&registers[4 * SR_REGNUM(10)];
805 To.Space = UDI29KSpecialRegs;
806 Count = 3;
807 if (USE_SHADOW_PC)
808 To.Offset = 20; /* SPC0 */
809 else
810 To.Offset = 10; /* PC0 */
811 if(UDIWrite(From, To, Count, Size, &CountDone, HostEndian))
812 error("UDIWrite() failed in udi_store_regisetrs");
813
814 /* LRU and MMU */
815
816 From = (UDIUInt32 *)&registers[4 * SR_REGNUM(13)];
817 To.Space = UDI29KSpecialRegs;
818 To.Offset = 13;
819 Count = 2;
820 if(UDIWrite(From, To, Count, Size, &CountDone, HostEndian))
821 error("UDIWrite() failed in udi_store_regisetrs");
822
823 /* Unprotected Special Registers */
824
825 From = (UDIUInt32 *)&registers[4 * SR_REGNUM(128)];
826 To.Space = UDI29KSpecialRegs;
827 To.Offset = 128;
828 Count = 135-128 +1;
829 if(UDIWrite(From, To, Count, Size, &CountDone, HostEndian))
830 error("UDIWrite() failed in udi_store_regisetrs");
831
832 registers_changed ();
833 }
834
835 /****************************************************** UDI_PREPARE_TO_STORE */
836 /* Get ready to modify the registers array. On machines which store
837 individual registers, this doesn't need to do anything. On machines
838 which store all the registers in one fell swoop, this makes sure
839 that registers contains all the registers from the program being
840 debugged. */
841
842 static void
843 udi_prepare_to_store ()
844 {
845 /* Do nothing, since we can store individual regs */
846 }
847
848 /********************************************************** TRANSLATE_ADDR */
849 static CORE_ADDR
850 translate_addr(addr)
851 CORE_ADDR addr;
852 {
853 #if defined(ULTRA3) && defined(KERNEL_DEBUGGING)
854 /* Check for a virtual address in the kernel */
855 /* Assume physical address of ublock is in paddr_u register */
856 /* FIXME: doesn't work for user virtual addresses */
857 if (addr >= UVADDR) {
858 /* PADDR_U register holds the physical address of the ublock */
859 CORE_ADDR i = (CORE_ADDR)read_register(PADDR_U_REGNUM);
860 return(i + addr - (CORE_ADDR)UVADDR);
861 } else {
862 return(addr);
863 }
864 #else
865 return(addr);
866 #endif
867 }
868 /************************************************* UDI_XFER_INFERIOR_MEMORY */
869 /* FIXME! Merge these two. */
870 static int
871 udi_xfer_inferior_memory (memaddr, myaddr, len, write)
872 CORE_ADDR memaddr;
873 char *myaddr;
874 int len;
875 int write;
876 {
877
878 memaddr = translate_addr(memaddr);
879
880 if (write)
881 return udi_write_inferior_memory (memaddr, myaddr, len);
882 else
883 return udi_read_inferior_memory (memaddr, myaddr, len);
884 }
885
886 /********************************************************** UDI_FILES_INFO */
887 static void
888 udi_files_info ()
889 {
890 printf ("\tAttached to UDI socket to %s and running program %s.\n",
891 udi_config_id, prog_name);
892 }
893
894 /**************************************************** UDI_INSERT_BREAKPOINT */
895 static int
896 udi_insert_breakpoint (addr, contents_cache)
897 CORE_ADDR addr;
898 char *contents_cache;
899 {
900 int cnt;
901 UDIError err;
902
903 for (cnt = 0; cnt < BKPT_TABLE_SIZE; cnt++)
904 if (bkpt_table[cnt].Type == 0) /* Find first free slot */
905 break;
906
907 if(cnt >= BKPT_TABLE_SIZE)
908 error("Too many breakpoints set");
909
910 bkpt_table[cnt].Addr.Offset = addr;
911 bkpt_table[cnt].Addr.Space = UDI29KIRAMSpace;
912 bkpt_table[cnt].PassCount = 1;
913 bkpt_table[cnt].Type = UDIBreakFlagExecute;
914
915 err = UDISetBreakpoint(bkpt_table[cnt].Addr,
916 bkpt_table[cnt].PassCount,
917 bkpt_table[cnt].Type,
918 &bkpt_table[cnt].BreakId);
919
920 if (err == 0) return 0; /* Success */
921
922 bkpt_table[cnt].Type = 0;
923 error("UDISetBreakpoint returned error code %d\n", err);
924 }
925
926 /**************************************************** UDI_REMOVE_BREAKPOINT */
927 static int
928 udi_remove_breakpoint (addr, contents_cache)
929 CORE_ADDR addr;
930 char *contents_cache;
931 {
932 int cnt;
933 UDIError err;
934
935 for (cnt = 0; cnt < BKPT_TABLE_SIZE; cnt++)
936 if (bkpt_table[cnt].Addr.Offset == addr) /* Find matching breakpoint */
937 break;
938
939 if(cnt >= BKPT_TABLE_SIZE)
940 error("Can't find breakpoint in table");
941
942 bkpt_table[cnt].Type = 0;
943
944 err = UDIClearBreakpoint(bkpt_table[cnt].BreakId);
945 if (err == 0) return 0; /* Success */
946
947 error("UDIClearBreakpoint returned error code %d\n", err);
948 }
949
950 /***************************************************************** UDI_KILL */
951 static void
952 udi_kill(arg,from_tty)
953 char *arg;
954 int from_tty;
955 {
956 char buf[4];
957
958 #if defined(ULTRA3) && defined(KERNEL_DEBUGGING)
959 /* We don't ever kill the kernel */
960 if (from_tty) {
961 printf_filtered("Kernel not killed, but left in current state.\n");
962 printf_filtered("Use detach to leave kernel running.\n");
963 }
964 #else
965 UDIStop();
966 inferior_pid = 0;
967 if (from_tty) {
968 printf("Target has been stopped.");
969 }
970 pop_target();
971 #endif
972 }
973
974
975
976 /***************************************************************** UDI_LOAD */
977 /*
978 * Load a program into the target.
979 */
980 static void
981 udi_load(arg_string,from_tty)
982 char *arg_string;
983 int from_tty;
984 {
985 #define MAX_TOKENS 25
986 #define BUFFER_SIZE 256
987 int token_count;
988 char *token[MAX_TOKENS];
989 char cmd_line[BUFFER_SIZE];
990
991 dont_repeat ();
992
993 #if defined(KERNEL_DEBUGGING) && defined(ULTRA3)
994 printf("The kernel had better be loaded already! Loading not done.\n");
995 #else
996 if (prog_name == 0)
997 error ("No program name");
998 arg_string = tilde_expand (arg_string);
999 sprintf(cmd_line,"y %s %s", prog_name, arg_string);
1000
1001 token_count = 0;
1002 token[0] = cmd_line;
1003
1004 if (cmd_line[0] != '\0')
1005 { token[token_count] = strtok(cmd_line, " \t,;\n\r");
1006
1007 if (token[token_count] != NULL)
1008 { do {
1009 token_count = token_count + 1;
1010 token[token_count] = strtok((char *) NULL, " \t,;\n\r");
1011 } while ((token[token_count] != NULL) &&
1012 (token_count < MAX_TOKENS));
1013 }
1014 else
1015 *token[0] = '\0';
1016 }
1017 make_cleanup (free, arg_string);
1018 QUIT;
1019 immediate_quit++;
1020 if(yank_cmd(token, token_count))
1021 error("Failure when tring to load program");
1022 immediate_quit--;
1023 symbol_file_add (prog_name, from_tty, 0, 0, 0, 0);/*DEBUG need to add text_addr */
1024 #endif
1025
1026 }
1027
1028 /*************************************************** UDI_WRITE_INFERIOR_MEMORY
1029 ** Copy LEN bytes of data from debugger memory at MYADDR
1030 to inferior's memory at MEMADDR. Returns number of bytes written. */
1031 static int
1032 udi_write_inferior_memory (memaddr, myaddr, len)
1033 CORE_ADDR memaddr;
1034 char *myaddr;
1035 int len;
1036 {
1037 int nwritten = 0;
1038 UDIUInt32 *From;
1039 UDIResource To;
1040 UDICount Count;
1041 UDISizeT Size = 1;
1042 UDICount CountDone = 0;
1043 UDIBool HostEndian = 0;
1044
1045 To.Space = udi_memory_space(memaddr);
1046 From = (UDIUInt32*)myaddr;
1047
1048 while (nwritten < len)
1049 { Count = len - nwritten;
1050 if (Count > MAXDATA) Count = MAXDATA;
1051 To.Offset = memaddr + nwritten;
1052 if(UDIWrite(From, To, Count, Size, &CountDone, HostEndian))
1053 { error("UDIWrite() failed in udi_write_inferrior_memory");
1054 break;
1055 }
1056 else
1057 { nwritten += CountDone;
1058 From += CountDone;
1059 }
1060 }
1061 return(nwritten);
1062 }
1063
1064 /**************************************************** UDI_READ_INFERIOR_MEMORY
1065 ** Read LEN bytes from inferior memory at MEMADDR. Put the result
1066 at debugger address MYADDR. Returns number of bytes read. */
1067 static int
1068 udi_read_inferior_memory(memaddr, myaddr, len)
1069 CORE_ADDR memaddr;
1070 char *myaddr;
1071 int len;
1072 {
1073 int nread = 0;
1074 UDIResource From;
1075 UDIUInt32 *To;
1076 UDICount Count;
1077 UDISizeT Size = 1;
1078 UDICount CountDone = 0;
1079 UDIBool HostEndian = 0;
1080
1081 From.Space = udi_memory_space(memaddr);
1082 To = (UDIUInt32*)myaddr;
1083
1084 while (nread < len)
1085 { Count = len - nread;
1086 if (Count > MAXDATA) Count = MAXDATA;
1087 From.Offset = memaddr + nread;
1088 if(UDIRead(From, To, Count, Size, &CountDone, HostEndian))
1089 { error("UDIWrite() failed in udi_read_inferrior_memory");
1090 break;
1091 }
1092 else
1093 { nread += CountDone;
1094 To += CountDone;
1095 }
1096 }
1097 return(nread);
1098 }
1099
1100 /********************************************************************* WARNING
1101 */
1102 udi_warning(num)
1103 int num;
1104 {
1105 error ("ERROR while loading program into remote TIP: $d\n", num);
1106 }
1107
1108
1109 /*****************************************************************************/
1110 /* Fetch a single register indicatated by 'regno'.
1111 * Returns 0/-1 on success/failure.
1112 */
1113 static void
1114 fetch_register (regno)
1115 int regno;
1116 {
1117 UDIResource From;
1118 UDIUInt32 To;
1119 UDICount Count = 1;
1120 UDISizeT Size = 4;
1121 UDICount CountDone;
1122 UDIBool HostEndian = 0;
1123 int result;
1124
1125 if (regno == GR1_REGNUM)
1126 {
1127 From.Space = UDI29KGlobalRegs;
1128 From.Offset = 1;
1129 }
1130 else if (regno >= GR96_REGNUM && regno < GR96_REGNUM + 32)
1131 {
1132 From.Space = UDI29KGlobalRegs;
1133 From.Offset = (regno - GR96_REGNUM) + 96;;
1134 }
1135
1136 #if defined(GR64_REGNUM)
1137
1138 else if (regno >= GR64_REGNUM && regno < GR64_REGNUM + 32 )
1139 {
1140 From.Space = UDI29KGlobalRegs;
1141 From.Offset = (regno - GR64_REGNUM) + 64;
1142 }
1143
1144 #endif /* GR64_REGNUM */
1145
1146 else if (regno >= LR0_REGNUM && regno < LR0_REGNUM + 128)
1147 {
1148 From.Space = UDI29KLocalRegs;
1149 From.Offset = (regno - LR0_REGNUM);
1150 }
1151 else if (regno>=FPE_REGNUM && regno<=EXO_REGNUM)
1152 {
1153 int val = -1;
1154 supply_register(160 + (regno - FPE_REGNUM),(char *) &val);
1155 return; /* Pretend Success */
1156 }
1157 else
1158 {
1159 From.Space = UDI29KSpecialRegs;
1160 From.Offset = regnum_to_srnum(regno);
1161 }
1162
1163 if (UDIRead(From, &To, Count, Size, &CountDone, HostEndian))
1164 error("UDIRead() failed in udi_fetch_registers");
1165
1166 supply_register(regno, (char *) &To);
1167
1168 if (kiodebug)
1169 printf("Fetching register %s = 0x%x\n", reg_names[regno], To);
1170 }
1171 /*****************************************************************************/
1172 /* Store a single register indicated by 'regno'.
1173 * Returns 0/-1 on success/failure.
1174 */
1175 static int
1176 store_register (regno)
1177 int regno;
1178 {
1179 int result;
1180 UDIUInt32 From;
1181 UDIResource To;
1182 UDICount Count = 1;
1183 UDISizeT Size = 4;
1184 UDICount CountDone;
1185 UDIBool HostEndian = 0;
1186
1187 From = read_register (regno); /* get data value */
1188
1189 if (kiodebug)
1190 printf("Storing register %s = 0x%x\n", reg_names[regno], From);
1191
1192 if (regno == GR1_REGNUM)
1193 { To.Space = UDI29KGlobalRegs;
1194 To.Offset = 1;
1195 result = UDIWrite(&From, To, Count, Size, &CountDone, HostEndian);
1196 /* Setting GR1 changes the numbers of all the locals, so invalidate the
1197 * register cache. Do this *after* calling read_register, because we want
1198 * read_register to return the value that write_register has just stuffed
1199 * into the registers array, not the value of the register fetched from
1200 * the inferior.
1201 */
1202 registers_changed ();
1203 }
1204 #if defined(GR64_REGNUM)
1205 else if (regno >= GR64_REGNUM && regno < GR64_REGNUM + 32 )
1206 { To.Space = UDI29KGlobalRegs;
1207 To.Offset = (regno - GR64_REGNUM) + 64;
1208 result = UDIWrite(&From, To, Count, Size, &CountDone, HostEndian);
1209 }
1210 #endif /* GR64_REGNUM */
1211 else if (regno >= GR96_REGNUM && regno < GR96_REGNUM + 32)
1212 { To.Space = UDI29KGlobalRegs;
1213 To.Offset = (regno - GR96_REGNUM) + 96;
1214 result = UDIWrite(&From, To, Count, Size, &CountDone, HostEndian);
1215 }
1216 else if (regno >= LR0_REGNUM && regno < LR0_REGNUM + 128)
1217 { To.Space = UDI29KLocalRegs;
1218 To.Offset = (regno - LR0_REGNUM);
1219 result = UDIWrite(&From, To, Count, Size, &CountDone, HostEndian);
1220 }
1221 else if (regno>=FPE_REGNUM && regno<=EXO_REGNUM)
1222 {
1223 return 0; /* Pretend Success */
1224 }
1225 else /* An unprotected or protected special register */
1226 { To.Space = UDI29KSpecialRegs;
1227 To.Offset = regnum_to_srnum(regno);
1228 result = UDIWrite(&From, To, Count, Size, &CountDone, HostEndian);
1229 }
1230
1231 if(result)
1232 { result = -1;
1233 error("UDIWrite() failed in store_registers");
1234 }
1235 return result;
1236 }
1237 /********************************************************** REGNUM_TO_SRNUM */
1238 /*
1239 * Convert a gdb special register number to a 29000 special register number.
1240 */
1241 static int
1242 regnum_to_srnum(regno)
1243 int regno;
1244 {
1245 switch(regno) {
1246 case VAB_REGNUM: return(0);
1247 case OPS_REGNUM: return(1);
1248 case CPS_REGNUM: return(2);
1249 case CFG_REGNUM: return(3);
1250 case CHA_REGNUM: return(4);
1251 case CHD_REGNUM: return(5);
1252 case CHC_REGNUM: return(6);
1253 case RBP_REGNUM: return(7);
1254 case TMC_REGNUM: return(8);
1255 case TMR_REGNUM: return(9);
1256 case NPC_REGNUM: return(USE_SHADOW_PC ? (20) : (10));
1257 case PC_REGNUM: return(USE_SHADOW_PC ? (21) : (11));
1258 case PC2_REGNUM: return(USE_SHADOW_PC ? (22) : (12));
1259 case MMU_REGNUM: return(13);
1260 case LRU_REGNUM: return(14);
1261 case IPC_REGNUM: return(128);
1262 case IPA_REGNUM: return(129);
1263 case IPB_REGNUM: return(130);
1264 case Q_REGNUM: return(131);
1265 case ALU_REGNUM: return(132);
1266 case BP_REGNUM: return(133);
1267 case FC_REGNUM: return(134);
1268 case CR_REGNUM: return(135);
1269 case FPE_REGNUM: return(160);
1270 case INTE_REGNUM: return(161);
1271 case FPS_REGNUM: return(162);
1272 case EXO_REGNUM:return(164);
1273 default:
1274 return(255); /* Failure ? */
1275 }
1276 }
1277 /****************************************************************************/
1278 /*
1279 * Determine the Target memory space qualifier based on the addr.
1280 * FIXME: Can't distinguis I_ROM/D_ROM.
1281 * FIXME: Doesn't know anything about I_CACHE/D_CACHE.
1282 */
1283 static CPUSpace
1284 udi_memory_space(addr)
1285 CORE_ADDR *addr;
1286 {
1287 UDIUInt32 tstart = IMemStart;
1288 UDIUInt32 tend = tstart + IMemSize;
1289 UDIUInt32 dstart = DMemStart;
1290 UDIUInt32 dend = tstart + DMemSize;
1291 UDIUInt32 rstart = RMemStart;
1292 UDIUInt32 rend = tstart + RMemSize;
1293
1294 if (((UDIUInt32)addr >= tstart) && ((UDIUInt32)addr < tend)) {
1295 return UDI29KIRAMSpace;
1296 } else if (((UDIUInt32)addr >= dstart) && ((UDIUInt32)addr < dend)) {
1297 return UDI29KDRAMSpace;
1298 } else if (((UDIUInt32)addr >= rstart) && ((UDIUInt32)addr < rend)) {
1299 /* FIXME: how do we determine between D_ROM and I_ROM */
1300 return UDI29KIROMSpace;
1301 } else /* FIXME: what do me do now? */
1302 return UDI29KDRAMSpace; /* Hmmm! */
1303 }
1304 /*********************************************************************** STUBS
1305 */
1306
1307 void convert16() {;}
1308 void convert32() {;}
1309 FILE* EchoFile = 0; /* used for debugging */
1310 int QuietMode = 0; /* used for debugging */
1311
1312 /****************************************************************************/
1313 /*
1314 * Define the target subroutine names
1315 */
1316 static struct target_ops udi_ops = {
1317 "udi",
1318 "Remote UDI connected TIP",
1319 "Remote debug an AMD 29k using UDI socket connection to TIP process",
1320 udi_open,
1321 udi_close,
1322 udi_attach,
1323 udi_detach,
1324 udi_resume,
1325 udi_wait,
1326 udi_fetch_registers,
1327 udi_store_registers,
1328 udi_prepare_to_store,
1329 udi_xfer_inferior_memory,
1330 udi_files_info,
1331 udi_insert_breakpoint,
1332 udi_remove_breakpoint,
1333 0, /* termial_init */
1334 0, /* terminal_inferior */
1335 0, /* terminal_ours_for_output */
1336 0, /* terminal_ours */
1337 0, /* terminal_info */
1338 udi_kill, /* FIXME, kill */
1339 udi_load,
1340 0, /* lookup_symbol */
1341 udi_create_inferior,
1342 udi_mourn, /* mourn_inferior FIXME */
1343 0, /* can_run */
1344 0, /* notice_signals */
1345 process_stratum,
1346 0, /* next */
1347 1, /* has_all_memory */
1348 1, /* has_memory */
1349 1, /* has_stack */
1350 1, /* has_registers */
1351 1, /* has_execution */
1352 0, /* sections */
1353 0, /* sections_end */
1354 OPS_MAGIC, /* Always the last thing */
1355 };
1356
1357 void _initialize_remote_udi()
1358 {
1359 add_target (&udi_ops);
1360 add_show_from_set (
1361 add_set_cmd ("remotedebug", no_class, var_boolean,
1362 (char *)&kiodebug,
1363 "Set debugging of UDI I/O.\n\
1364 When enabled, debugging info is displayed.",
1365 &setlist),
1366 &showlist);
1367 }
1368
1369 #ifdef NO_HIF_SUPPORT
1370 service_HIF(msg)
1371 union msg_t *msg;
1372 {
1373 return(0); /* Emulate a failure */
1374 }
1375 #endif