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