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.
5 This file is part of GDB.
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.
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.
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. */
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.
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
36 - Daniel Mann at AMD took the 3.95 adaptions above and replaced
37 MiniMON interface with UDI-p interface. */
50 #include "29k-share/udi/udiproc.h"
52 /* access the register store directly, without going through
53 the normal handler functions. This avoids an extra data copy
56 /* #define DEBUG 1 /* */
58 # define DENTER(NAME) (printf("Entering %s\n",NAME), fflush(stdout))
59 # define DEXIT(NAME) (printf("Exiting %s\n",NAME), fflush(stdout))
66 extern int stop_soon_quietly; /* for wait_for_inferior */
67 extern struct value *call_function_by_hand();
68 static void udi_resume();
69 static void udi_fetch_registers ();
70 static void udi_load();
71 static int fetch_register ();
72 static void udi_store_registers ();
73 static int store_register ();
74 static int regnum_to_srnum();
75 static void udi_close ();
76 static CPUSpace udi_memory_space();
77 static int udi_write_inferior_memory();
78 static int udi_read_inferior_memory();
79 char CoffFileName[100] = "";
83 #define TYPE_UNKNOWN 0
87 static char *processor_name[] = { "Unknown", "Am29000", "Am29030", "Am29050" };
88 static int processor_type=TYPE_UNKNOWN;
89 #define FREEZE_MODE (read_register(CPS_REGNUM) && 0x400)
90 #define USE_SHADOW_PC ((processor_type == TYPE_A29050) && FREEZE_MODE)
92 #define LLOG_FILE "udi.log"
93 #if defined (LOG_FILE)
97 static int timeout = 5;
98 extern struct target_ops udi_ops; /* Forward declaration */
100 /* Special register enumeration.
103 /******************************************************************* UDI DATA*/
104 #define MAXDATA 2*1024 /* max UDI[read/write] byte size */
105 /* Descriptor for I/O to remote machine. Initialize it to -1 so that
106 udi_open knows that we don't have a file open when the program
108 UDISessionId udi_session_id = -1;
110 CPUOffset IMemStart = 0;
111 CPUSizeT IMemSize = 0;
112 CPUOffset DMemStart = 0;
113 CPUSizeT DMemSize = 0;
114 CPUOffset RMemStart = 0;
115 CPUSizeT RMemSize = 0;
119 #define SBUF_MAX 1024 /* maximum size of string handling buffer */
122 typedef struct bkpt_entry_str
127 unsigned int BreakId;
129 #define BKPT_TABLE_SIZE 40
130 static bkpt_entry_t bkpt_table[BKPT_TABLE_SIZE];
131 extern char dfe_errmsg[]; /* error string */
133 /*********************************************************** SIGNAL SUPPORT */
134 /* Called when SIGALRM signal sent due to alarm() timeout. */
139 # define volatile /**/
142 volatile int n_alarms;
149 printf ("udi_timer called\n");
153 #endif /* HAVE_TERMIO */
155 /* malloc'd name of the program on the remote system. */
156 static char *prog_name = NULL;
159 /* Number of SIGTRAPs we need to simulate. That is, the next
160 NEED_ARTIFICIAL_TRAP calls to udi_wait should just return
161 SIGTRAP without actually waiting for anything. */
163 /******************************************************* UDI_CREATE_INFERIOR */
164 /* This is called not only when we first attach, but also when the
165 user types "run" after having attached. */
167 udi_create_inferior (execfile, args, env)
172 DENTER("udi_create_inferior()");
175 { if (prog_name != NULL)
177 prog_name = savestring (execfile, strlen (execfile));
180 if (prog_name == 0 /* || exec_bfd == 0 */ )
181 error ("No exec file specified");
183 if (udi_session_id < 0){
184 printf("UDI connection not open yet.\n");
188 inferior_pid = 40000;
190 #if defined(ULTRA3) && defined(KERNEL_DEBUGGING)
191 /* On ultra3 (NYU) we assume the kernel is already running so there is
192 * no file to download
195 if(*args == '\0') args = prog_name;
199 /* We will get a task spawn event immediately. */
200 #ifdef NOTDEF /* start_remote() now does a wait without a resume
204 init_wait_for_inferior ();
205 clear_proceed_status ();
208 DEXIT("udi_create_inferior()");
210 /******************************************************* UDI_MOURN_INFERIOR */
214 DENTER("udi_mourn()");
215 pop_target (); /* Pop back to no-child state */
216 generic_mourn_inferior ();
217 DEXIT("udi_mourn()");
220 /******************************************************************** UDI_OPEN
221 ** Open a connection to remote TIP.
222 NAME is the socket domain used for communication with the TIP,
223 then a space and the socket name or TIP-host name.
224 '<udi_udi_config_id> [progname]' for example.
227 /* XXX - need cleanups for udiconnect for various failures!!! */
229 static char *udi_config_id;
231 udi_open (name, from_tty)
238 UDIMemoryRange KnownMemory[10];
239 UDIUInt32 ChipVersions[10];
240 UDIInt NumberOfRanges = 10;
241 UDIInt NumberOfChips = 10;
243 UDIUInt32 TIPId, TargetId, DFEId, DFE, TIP, DFEIPCId, TIPIPCId;
245 DENTER("udi_open()");
247 target_preopen(from_tty);
249 /* Find the first whitespace character, it separates udi_config_id
251 if(!name) goto erroid;
253 *p != '\0' && !isspace (*p); p++)
257 error("Usage: target udi config_id progname, where config_id appears in udi_soc file");
259 udi_config_id = (char*)malloc (p - name + 1);
260 strncpy (udi_config_id, name, p - name);
261 udi_config_id[p - name] = '\0';
263 /* Skip over the whitespace after udi_config_id */
264 for (; isspace (*p); p++)
267 if (prog_name != NULL)
269 prog_name = savestring (p, strlen (p));
271 if (UDIConnect(udi_config_id, &udi_session_id))
272 error("UDIConnect() failed: %s\n", dfe_errmsg);
274 push_target (&udi_ops);
277 #ifndef NO_SIGINTERRUPT
278 /* Cause SIGALRM's to make reads fail with EINTR instead of resuming
280 if (siginterrupt (SIGALRM, 1) != 0)
281 error ("udi_open: siginterrupt() %s", safe_strerror(errno));
284 /* Set up read timeout timer. */
285 if ((void (*)) signal (SIGALRM, udi_timer) == (void (*)) -1)
286 error ("udi_open: signal() %s", safe_strerror(errno));
289 #if defined (LOG_FILE)
290 log_file = fopen (LOG_FILE, "w");
291 if (log_file == NULL)
292 error ("udi_open: fopen(%s) %s", LOG_FILE, safe_strerror(errno));
295 ** Initialize target configuration structure (global)
297 if(UDIGetTargetConfig( KnownMemory, &NumberOfRanges,
298 ChipVersions, &NumberOfChips))
299 error ("UDIGetTargetConfig() failed");
300 if(NumberOfChips > 2)
301 fprintf(stderr,"Taret has more than one processor\n");
302 for(cnt=0; cnt<NumberOfRanges; cnt++)
303 { switch(KnownMemory[cnt].Space)
305 default: fprintf(stderr, "UDIGetTargetConfig() unknown memory space\n");
309 case UDI29KIROMSpace:
310 RMemStart = KnownMemory[cnt].Offset;
311 RMemSize = KnownMemory[cnt].Size;
313 case UDI29KIRAMSpace:
314 IMemStart = KnownMemory[cnt].Offset;
315 IMemSize = KnownMemory[cnt].Size;
317 case UDI29KDRAMSpace:
318 DMemStart = KnownMemory[cnt].Offset;
319 DMemSize = KnownMemory[cnt].Size;
324 /* Determine the processor revision level */
325 prl = (unsigned int)read_register(CFG_REGNUM) >> 24;
327 { fprintf_filtered(stderr,
328 "Remote debugging Am29000 rev %c\n",'A'+(prl&0x1f));
329 processor_type = TYPE_A29000;
330 } else if ((prl&0xe0) == 0x40) /* 29030 = 0x4* */
331 { fprintf_filtered(stderr,
332 "Remote debugging Am2903* rev %c\n",'A'+(prl&0x1f));
333 processor_type = TYPE_A29030;
334 } else if ((prl&0xe0) == 0x20) /* 29050 = 0x2* */
335 { fprintf_filtered(stderr,
336 "Remote debugging Am29050 rev %c\n",'A'+(prl&0x1f));
337 processor_type = TYPE_A29050;
339 processor_type = TYPE_UNKNOWN;
340 fprintf_filtered(stderr,"WARNING: processor type unknown.\n");
342 if(UDICreateProcess(&PId))
343 fprintf(stderr, "UDICreateProcess() failed\n");
345 /* Print out some stuff, letting the user now what's going on */
346 if(UDICapabilities( &TIPId, &TargetId, DFEId, DFE, &TIP, &DFEIPCId,
348 error ("UDICapabilities() failed");
350 printf_filtered("Remote debugging an %s connected via UDI socket,\n\
351 DFE-IPC version %x.%x.%x TIP-IPC version %x.%x.%x TIP version %x.%x.%x\n %s\n",
352 processor_name[processor_type],
353 (DFEIPCId>>8)&0xf, (DFEIPCId>>4)&0xf, DFEIPCId&0xf,
354 (TIPIPCId>>8)&0xf, (TIPIPCId>>4)&0xf, TIPIPCId&0xf,
355 (TargetId>>8)&0xf, (TargetId>>4)&0xf, TargetId&0xf,
358 /* FIXME: can this restriction be removed? */
359 printf_filtered("Remote debugging using virtual addresses works only\n");
360 printf_filtered(" when virtual addresses map 1:1 to physical addresses.\n");
364 if (processor_type != TYPE_A29050) {
365 fprintf_filtered(stderr,
366 "Freeze-mode debugging can only be done on an Am29050,\n");
367 fprintf_filtered(stderr,
368 " unless GDB is being used with a 29K simulator.\n");
373 /******************************************************************* UDI_CLOSE
374 Close the open connection to the TIP process.
375 Use this when you want to detach and do something else
378 udi_close (quitting) /*FIXME: how is quitting used */
382 DENTER("udi_close()");
384 if (udi_session_id < 0)
385 error ("Can't close udi connection: not debugging remotely.");
387 /* We should never get here if there isn't something valid in
390 if(UDIDisconnect(udi_stream, Terminate);)
391 error ("UDIDisconnect() failed in udi_close");
393 /* Do not try to close udi_session_id again, later in the program. */
397 #if defined (LOG_FILE)
398 if (ferror (log_file))
399 printf ("Error writing log file.\n");
400 if (fclose (log_file) != 0)
401 printf ("Error closing log file.\n");
404 printf_filtered (" Ending remote debugging\n");
406 DEXIT("udi_close()");
409 /**************************************************************** UDI_ATACH */
410 /* Attach to a program that is already loaded and running
411 * Upon exiting the process's execution is stopped.
414 udi_attach (args, from_tty)
423 UDIBool HostEndian = 0;
424 DENTER("udi_attach()");
426 if (udi_session_id < 0)
427 printf ("UDI connection not opened yet, use the 'target udi' command.\n");
430 printf ("Attaching to remote program %s...\n", prog_name);
432 mark_breakpoints_out ();
435 From.Offset = UDI29KSpecialRegs;
436 if(UDIRead(From, &PC_adds, Count, Size, &CountDone, HostEndian))
437 error ("UDIRead failed in udi_attach");
438 printf ("Remote process is now halted, pc1 = 0x%x.\n", PC_adds);
440 DEXIT("udi_attach()");
442 /************************************************************* UDI_DETACH */
443 /* Terminate the open connection to the TIP process.
444 Use this when you want to detach and do something else
445 with your gdb. Leave remote process running (with no breakpoints set). */
447 udi_detach (args,from_tty)
451 DENTER("udi_dettach()");
452 remove_breakpoints(); /* Just in case there were any left in */
453 if(UDIDisconnect(udi_session_id))
454 error ("UDIDisconnect() failed in udi_detach");
455 pop_target(); /* calls udi_close to do the real work */
457 printf ("Ending remote debugging\n");
458 DEXIT("udi_dettach()");
462 /****************************************************************** UDI_RESUME
463 ** Tell the remote machine to resume. */
466 udi_resume (step, sig)
471 UDIStepType StepType = UDIStepNatural;
473 DENTER("udi_resume()");
474 if (step) /* step 1 instruction */
475 { tip_error = tip_error = UDIStep(Steps, StepType, Range);
476 if(tip_error)fprintf(stderr, "UDIStep() error = %d\n", tip_error);
477 if(tip_error)error ("failed in udi_resume");
482 error ("UDIExecute() failed in udi_resume");
485 DEXIT("udi_resume()");
488 /******************************************************************** UDI_WAIT
489 ** Wait until the remote machine stops, then return,
490 storing status in STATUS just as `wait' would. */
500 int old_timeout = timeout;
501 int old_immediate_quit = immediate_quit;
504 DENTER("udi_wait()");
505 WSETEXIT ((*status), 0);
507 /* wait for message to arrive. It should be:
508 If the target stops executing, udi_wait() should return.
510 timeout = 0; /* Wait indefinetly for a message */
511 immediate_quit = 1; /* Helps ability to QUIT */
515 MaxTime = UDIWaitForever;
516 UDIWait(MaxTime, &PId, &StopReason);
517 QUIT; /* Let user quit if they want */
518 switch (StopReason & 0xff)
523 if(UDIGetStdout(sbuf, (UDISizeT)SBUF_MAX, &CountDone))
524 error("UDIGetStdin() failed in udi_wait");
525 while(CountDone--)putc(sbuf[i++], stdout);
529 UDIGetStderr(sbuf, (UDISizeT)SBUF_MAX, &CountDone);
530 while(CountDone--)putc(sbuf[i++], stderr);
535 printf("DEBUG: stdin requested ... continue\n");
536 /* UDIPutStdin(sbuf, (UDISizeT)i, &CountDone); */
544 if (StopReason & 0xff == UDITrapped ) /* lower 8-bits == 0 */
546 if (StopReason >> 24 == 0)
547 { printf("Am290*0 received vector number 0 (break point)\n");
548 WSETSTOP ((*status), SIGTRAP);
550 else if (StopReason >> 24 == 1)
551 { printf("Am290*0 received vector 1\n");
552 WSETSTOP ((*status), SIGBUS);
554 else if (StopReason >> 24 == 3
555 || StopReason >> 24 == 4)
556 { printf("Am290*0 received vector number %d\n",
558 WSETSTOP ((*status), SIGFPE);
560 else if (StopReason >> 24 == 5)
561 { printf("Am290*0 received vector number %d\n",
563 WSETSTOP ((*status), SIGILL);
565 else if (StopReason >> 24 >= 6
566 && StopReason >> 24 <= 11)
567 { printf("Am290*0 received vector number %d\n",
569 WSETSTOP ((*status), SIGSEGV);
571 else if (StopReason >> 24 == 12
572 || StopReason >> 24 == 13)
573 { printf("Am290*0 received vector number %d\n",
575 WSETSTOP ((*status), SIGILL);
577 else if ((StopReason & 0xff) == 14)
578 { printf("Am290*0 received vector number %d\n",
580 WSETSTOP ((*status), SIGALRM);
582 else if ((StopReason & 0xff) == 15)
583 WSETSTOP ((*status), SIGTRAP);
584 else if ((StopReason >> 24) >= 16
585 && (StopReason >> 24) <= 21)
586 { printf("Am290*0 received vector number %d\n",
588 WSETSTOP ((*status), SIGINT);
590 else if ((StopReason & 0xff) == 22)
591 { printf("Am290*0 received vector number %d\n",
593 WSETSTOP ((*status), SIGILL);
595 else if ((StopReason & 0xff) == 77)
596 WSETSTOP ((*status), SIGTRAP);
599 WSETEXIT ((*status), 0);
601 else if ((StopReason & 0xff) == UDIBreak)
602 WSETSTOP ((*status), SIGTRAP);
603 else if ((StopReason & 0xff) == UDINotExecuting)
604 WSETSTOP ((*status), SIGTERM);
605 else if ((StopReason & 0xff) == UDIRunning)
606 WSETSTOP ((*status), SIGILL);
607 else if ((StopReason & 0xff) == UDIStopped)
608 WSETSTOP ((*status), SIGTSTP);
609 else if ((StopReason & 0xff) == UDIWarned)
610 WSETSTOP ((*status), SIGLOST);
611 else if ((StopReason & 0xff) == UDIStepped)
612 WSETSTOP ((*status), SIGTRAP);
613 else if ((StopReason & 0xff) == UDIWaiting)
614 WSETSTOP ((*status), SIGSTOP);
615 else if ((StopReason & 0xff) == UDIHalted)
616 WSETSTOP ((*status), SIGKILL);
618 WSETEXIT ((*status), 0);
620 timeout = old_timeout; /* Restore original timeout value */
621 immediate_quit = old_immediate_quit;
626 /********************************************************** UDI_FETCH_REGISTERS
627 * Read a remote register 'regno'.
628 * If regno==-1 then read all the registers.
631 udi_fetch_registers (regno)
639 UDIBool HostEndian = 0;
643 fetch_register(regno);
649 From.Space = UDI29KGlobalRegs;
651 To = (UDIUInt32 *)®isters[4 * GR1_REGNUM];
653 if (UDIRead(From, To, Count, Size, &CountDone, HostEndian))
654 error("UDIRead() failed in udi_fetch_registers");
656 register_valid[GR1_REGNUM] = 1;
658 #if defined(GR64_REGNUM) /* Read gr64-127 */
660 /* Global Registers gr64-gr95 */
662 From.Space = UDI29KGlobalRegs;
664 To = (UDIUInt32 *)®isters[4 * GR64_REGNUM];
666 if (UDIRead(From, To, Count, Size, &CountDone, HostEndian))
667 error("UDIRead() failed in udi_fetch_registers");
669 for (i = GR64_REGNUM; i < GR64_REGNUM + 32; i++)
670 register_valid[i] = 1;
672 #endif /* GR64_REGNUM */
674 /* Global Registers gr96-gr127 */
676 From.Space = UDI29KGlobalRegs;
678 To = (UDIUInt32 *)®isters[4 * GR96_REGNUM];
680 if (UDIRead(From, To, Count, Size, &CountDone, HostEndian))
681 error("UDIRead() failed in udi_fetch_registers");
683 for (i = GR96_REGNUM; i < GR96_REGNUM + 32; i++)
684 register_valid[i] = 1;
686 /* Local Registers */
688 From.Space = UDI29KLocalRegs;
690 To = (UDIUInt32 *)®isters[4 * LR0_REGNUM];
692 if (UDIRead(From, To, Count, Size, &CountDone, HostEndian))
693 error("UDIRead() failed in udi_fetch_registers");
695 for (i = LR0_REGNUM; i < LR0_REGNUM + 128; i++)
696 register_valid[i] = 1;
698 /* Protected Special Registers */
700 From.Space = UDI29KSpecialRegs;
702 To = (UDIUInt32 *)®isters[4 * SR_REGNUM(0)];
704 if (UDIRead(From, To, Count, Size, &CountDone, HostEndian))
705 error("UDIRead() failed in udi_fetch_registers");
707 for (i = SR_REGNUM(0); i < SR_REGNUM(0) + 15; i++)
708 register_valid[i] = 1;
710 if (USE_SHADOW_PC) { /* Let regno_to_srnum() handle the register number */
711 fetch_register(NPC_REGNUM);
712 fetch_register(PC_REGNUM);
713 fetch_register(PC2_REGNUM);
715 /* Unprotected Special Registers sr128-sr135 */
717 From.Space = UDI29KSpecialRegs;
719 To = (UDIUInt32 *)®isters[4 * SR_REGNUM(128)];
721 if (UDIRead(From, To, Count, Size, &CountDone, HostEndian))
722 error("UDIRead() failed in udi_fetch_registers");
724 for (i = SR_REGNUM(128); i < SR_REGNUM(128) + 135-128+1; i++)
725 register_valid[i] = 1;
728 /* There doesn't seem to be any way to get these. */
731 supply_register (FPE_REGNUM, (char *) &val);
732 supply_register (INTE_REGNUM, (char *) &val);
733 supply_register (FPS_REGNUM, (char *) &val);
734 supply_register (EXO_REGNUM, (char *) &val);
739 /********************************************************* UDI_STORE_REGISTERS
740 ** Store register regno into the target.
741 * If regno==-1 then store all the registers.
745 udi_store_registers (regno)
753 UDIBool HostEndian = 0;
757 store_register(regno);
763 From = (UDIUInt32 *)®isters[4 * GR1_REGNUM];
764 To.Space = UDI29KGlobalRegs;
767 if(UDIWrite(From, To, Count, Size, &CountDone, HostEndian))
768 error("UDIWrite() failed in udi_store_regisetrs");
770 #if defined(GR64_REGNUM)
772 /* Global registers gr64-gr95 */
774 From = (UDIUInt32 *)®isters[4 * GR64_REGNUM];
775 To.Space = UDI29KGlobalRegs;
778 if(UDIWrite(From, To, Count, Size, &CountDone, HostEndian))
779 error("UDIWrite() failed in udi_store_regisetrs");
781 #endif /* GR64_REGNUM */
783 /* Global registers gr96-gr127 */
785 From = (UDIUInt32 *)®isters[4 * GR96_REGNUM];
786 To.Space = UDI29KGlobalRegs;
789 if(UDIWrite(From, To, Count, Size, &CountDone, HostEndian))
790 error("UDIWrite() failed in udi_store_regisetrs");
792 /* Local Registers */
794 From = (UDIUInt32 *)®isters[4 * LR0_REGNUM];
795 To.Space = UDI29KLocalRegs;
798 if(UDIWrite(From, To, Count, Size, &CountDone, HostEndian))
799 error("UDIWrite() failed in udi_store_regisetrs");
802 /* Protected Special Registers */ /* VAB through TMR */
804 From = (UDIUInt32 *)®isters[4 * SR_REGNUM(0)];
805 To.Space = UDI29KSpecialRegs;
808 if(UDIWrite(From, To, Count, Size, &CountDone, HostEndian))
809 error("UDIWrite() failed in udi_store_regisetrs");
811 /* PC0, PC1, PC2 possibly as shadow registers */
813 From = (UDIUInt32 *)®isters[4 * SR_REGNUM(10)];
814 To.Space = UDI29KSpecialRegs;
817 To.Offset = 20; /* SPC0 */
819 To.Offset = 10; /* PC0 */
820 if(UDIWrite(From, To, Count, Size, &CountDone, HostEndian))
821 error("UDIWrite() failed in udi_store_regisetrs");
825 From = (UDIUInt32 *)®isters[4 * SR_REGNUM(13)];
826 To.Space = UDI29KSpecialRegs;
829 if(UDIWrite(From, To, Count, Size, &CountDone, HostEndian))
830 error("UDIWrite() failed in udi_store_regisetrs");
832 /* Unprotected Special Registers */
834 From = (UDIUInt32 *)®isters[4 * SR_REGNUM(128)];
835 To.Space = UDI29KSpecialRegs;
838 if(UDIWrite(From, To, Count, Size, &CountDone, HostEndian))
839 error("UDIWrite() failed in udi_store_regisetrs");
841 registers_changed ();
844 /****************************************************** UDI_PREPARE_TO_STORE */
845 /* Get ready to modify the registers array. On machines which store
846 individual registers, this doesn't need to do anything. On machines
847 which store all the registers in one fell swoop, this makes sure
848 that registers contains all the registers from the program being
852 udi_prepare_to_store ()
854 /* Do nothing, since we can store individual regs */
857 /********************************************************** TRANSLATE_ADDR */
862 #if defined(ULTRA3) && defined(KERNEL_DEBUGGING)
863 /* Check for a virtual address in the kernel */
864 /* Assume physical address of ublock is in paddr_u register */
865 /* FIXME: doesn't work for user virtual addresses */
866 if (addr >= UVADDR) {
867 /* PADDR_U register holds the physical address of the ublock */
868 CORE_ADDR i = (CORE_ADDR)read_register(PADDR_U_REGNUM);
869 return(i + addr - (CORE_ADDR)UVADDR);
877 /************************************************* UDI_XFER_INFERIOR_MEMORY */
878 /* FIXME! Merge these two. */
880 udi_xfer_inferior_memory (memaddr, myaddr, len, write)
887 memaddr = translate_addr(memaddr);
890 return udi_write_inferior_memory (memaddr, myaddr, len);
892 return udi_read_inferior_memory (memaddr, myaddr, len);
895 /********************************************************** UDI_FILES_INFO */
899 printf ("\tAttached to UDI socket to %s and running program %s.\n",
900 udi_config_id, prog_name);
903 /**************************************************** UDI_INSERT_BREAKPOINT */
905 udi_insert_breakpoint (addr, contents_cache)
907 char *contents_cache;
912 for (cnt = 0; cnt < BKPT_TABLE_SIZE; cnt++)
913 if (bkpt_table[cnt].Type == 0) /* Find first free slot */
916 if(cnt >= BKPT_TABLE_SIZE)
917 error("Too many breakpoints set");
919 bkpt_table[cnt].Addr.Offset = addr;
920 bkpt_table[cnt].Addr.Space = UDI29KIRAMSpace;
921 bkpt_table[cnt].PassCount = 1;
922 bkpt_table[cnt].Type = UDIBreakFlagExecute;
924 err = UDISetBreakpoint(bkpt_table[cnt].Addr,
925 bkpt_table[cnt].PassCount,
926 bkpt_table[cnt].Type,
927 &bkpt_table[cnt].BreakId);
929 if (err == 0) return 0; /* Success */
931 bkpt_table[cnt].Type = 0;
932 error("UDISetBreakpoint returned error code %d\n", err);
935 /**************************************************** UDI_REMOVE_BREAKPOINT */
937 udi_remove_breakpoint (addr, contents_cache)
939 char *contents_cache;
944 for (cnt = 0; cnt < BKPT_TABLE_SIZE; cnt++)
945 if (bkpt_table[cnt].Addr.Offset == addr) /* Find matching breakpoint */
948 if(cnt >= BKPT_TABLE_SIZE)
949 error("Can't find breakpoint in table");
951 bkpt_table[cnt].Type = 0;
953 err = UDIClearBreakpoint(bkpt_table[cnt].BreakId);
954 if (err == 0) return 0; /* Success */
956 error("UDIClearBreakpoint returned error code %d\n", err);
959 /***************************************************************** UDI_KILL */
961 udi_kill(arg,from_tty)
967 DENTER("udi_kill()");
968 #if defined(ULTRA3) && defined(KERNEL_DEBUGGING)
969 /* We don't ever kill the kernel */
971 printf_filtered("Kernel not killed, but left in current state.\n");
972 printf_filtered("Use detach to leave kernel running.\n");
978 printf("Target has been stopped.");
987 /***************************************************************** UDI_LOAD */
989 * Load a program into the target.
992 udi_load(arg_string,from_tty)
996 #define MAX_TOKENS 25
997 #define BUFFER_SIZE 256
999 char *token[MAX_TOKENS];
1000 char cmd_line[BUFFER_SIZE];
1004 #if defined(KERNEL_DEBUGGING) && defined(ULTRA3)
1005 printf("The kernel had better be loaded already! Loading not done.\n");
1007 if (arg_string == 0)
1008 error ("The load command takes a file name");
1009 arg_string = tilde_expand (arg_string);
1010 sprintf(cmd_line,"y %s %s", prog_name, arg_string);
1013 token[0] = cmd_line;
1015 if (cmd_line[0] != '\0')
1016 { token[token_count] = strtok(cmd_line, " \t,;\n\r");
1018 if (token[token_count] != NULL)
1020 token_count = token_count + 1;
1021 token[token_count] = strtok((char *) NULL, " \t,;\n\r");
1022 } while ((token[token_count] != NULL) &&
1023 (token_count < MAX_TOKENS));
1028 make_cleanup (free, arg_string);
1031 if(yank_cmd(token, token_count))
1032 error("Failure when tring to load program");
1034 symbol_file_add (arg_string, from_tty, 0, 0, 0, 0);/*DEBUG need to add text_addr */
1039 /*************************************************** UDI_WRITE_INFERIOR_MEMORY
1040 ** Copy LEN bytes of data from debugger memory at MYADDR
1041 to inferior's memory at MEMADDR. Returns number of bytes written. */
1043 udi_write_inferior_memory (memaddr, myaddr, len)
1053 UDICount CountDone = 0;
1054 UDIBool HostEndian = 0;
1057 /* DENTER("udi_write_inferior_memory()"); */
1058 To.Space = udi_memory_space(memaddr);
1059 From = (UDIUInt32*)myaddr;
1061 while (nwritten < len)
1062 { Count = len - nwritten;
1063 if (Count > MAXDATA) Count = MAXDATA;
1064 To.Offset = memaddr + nwritten;
1065 if(UDIWrite(From, To, Count, Size, &CountDone, HostEndian))
1066 { error("UDIWrite() failed in udi_write_inferrior_memory");
1070 { nwritten += CountDone;
1074 /* DEXIT("udi_write_inferior_memory()"); */
1078 /**************************************************** UDI_READ_INFERIOR_MEMORY
1079 ** Read LEN bytes from inferior memory at MEMADDR. Put the result
1080 at debugger address MYADDR. Returns number of bytes read. */
1082 udi_read_inferior_memory(memaddr, myaddr, len)
1092 UDICount CountDone = 0;
1093 UDIBool HostEndian = 0;
1096 /* DENTER("udi_read_inferior_memory()"); */
1097 From.Space = udi_memory_space(memaddr);
1098 To = (UDIUInt32*)myaddr;
1101 { Count = len - nread;
1102 if (Count > MAXDATA) Count = MAXDATA;
1103 From.Offset = memaddr + nread;
1104 if(UDIRead(From, To, Count, Size, &CountDone, HostEndian))
1105 { error("UDIWrite() failed in udi_read_inferrior_memory");
1109 { nread += CountDone;
1116 /********************************************************************* WARNING
1121 error ("ERROR while loading program into remote TIP: $d\n", num);
1125 /*****************************************************************************/
1126 /* Fetch a single register indicatated by 'regno'.
1127 * Returns 0/-1 on success/failure.
1130 fetch_register (regno)
1138 UDIBool HostEndian = 0;
1141 if (regno == GR1_REGNUM)
1143 From.Space = UDI29KGlobalRegs;
1146 else if (regno >= GR96_REGNUM && regno < GR96_REGNUM + 32)
1148 From.Space = UDI29KGlobalRegs;
1149 From.Offset = (regno - GR96_REGNUM) + 96;;
1152 #if defined(GR64_REGNUM)
1154 else if (regno >= GR64_REGNUM && regno < GR64_REGNUM + 32 )
1156 From.Space = UDI29KGlobalRegs;
1157 From.Offset = (regno - GR64_REGNUM) + 64;
1160 #endif /* GR64_REGNUM */
1162 else if (regno >= LR0_REGNUM && regno < LR0_REGNUM + 128)
1164 From.Space = UDI29KLocalRegs;
1165 From.Offset = (regno - LR0_REGNUM);
1167 else if (regno>=FPE_REGNUM && regno<=EXO_REGNUM)
1170 supply_register(160 + (regno - FPE_REGNUM),(char *) &val);
1171 return 0; /* Pretend Success */
1175 From.Space = UDI29KSpecialRegs;
1176 From.Offset = regnum_to_srnum(regno);
1179 if (UDIRead(From, &To, Count, Size, &CountDone, HostEndian))
1180 error("UDIRead() failed in udi_fetch_registers");
1182 supply_register(regno, (char *) &To);
1185 /*****************************************************************************/
1186 /* Store a single register indicated by 'regno'.
1187 * Returns 0/-1 on success/failure.
1190 store_register (regno)
1199 UDIBool HostEndian = 0;
1201 DENTER("store_register()");
1202 From = read_register (regno); /* get data value */
1204 if (regno == GR1_REGNUM)
1205 { To.Space = UDI29KGlobalRegs;
1207 result = UDIWrite(&From, To, Count, Size, &CountDone, HostEndian);
1208 /* Setting GR1 changes the numbers of all the locals, so invalidate the
1209 * register cache. Do this *after* calling read_register, because we want
1210 * read_register to return the value that write_register has just stuffed
1211 * into the registers array, not the value of the register fetched from
1214 registers_changed ();
1216 #if defined(GR64_REGNUM)
1217 else if (regno >= GR64_REGNUM && regno < GR64_REGNUM + 32 )
1218 { To.Space = UDI29KGlobalRegs;
1219 To.Offset = (regno - GR64_REGNUM) + 64;
1220 result = UDIWrite(&From, To, Count, Size, &CountDone, HostEndian);
1222 #endif /* GR64_REGNUM */
1223 else if (regno >= GR96_REGNUM && regno < GR96_REGNUM + 32)
1224 { To.Space = UDI29KGlobalRegs;
1225 To.Offset = (regno - GR96_REGNUM) + 96;
1226 result = UDIWrite(&From, To, Count, Size, &CountDone, HostEndian);
1228 else if (regno >= LR0_REGNUM && regno < LR0_REGNUM + 128)
1229 { To.Space = UDI29KLocalRegs;
1230 To.Offset = (regno - LR0_REGNUM);
1231 result = UDIWrite(&From, To, Count, Size, &CountDone, HostEndian);
1233 else if (regno>=FPE_REGNUM && regno<=EXO_REGNUM)
1235 return 0; /* Pretend Success */
1237 else /* An unprotected or protected special register */
1238 { To.Space = UDI29KSpecialRegs;
1239 To.Offset = regnum_to_srnum(regno);
1240 result = UDIWrite(&From, To, Count, Size, &CountDone, HostEndian);
1243 DEXIT("store_register()");
1246 error("UDIWrite() failed in store_registers");
1250 /********************************************************** REGNUM_TO_SRNUM */
1252 * Convert a gdb special register number to a 29000 special register number.
1255 regnum_to_srnum(regno)
1259 case VAB_REGNUM: return(0);
1260 case OPS_REGNUM: return(1);
1261 case CPS_REGNUM: return(2);
1262 case CFG_REGNUM: return(3);
1263 case CHA_REGNUM: return(4);
1264 case CHD_REGNUM: return(5);
1265 case CHC_REGNUM: return(6);
1266 case RBP_REGNUM: return(7);
1267 case TMC_REGNUM: return(8);
1268 case TMR_REGNUM: return(9);
1269 case NPC_REGNUM: return(USE_SHADOW_PC ? (20) : (10));
1270 case PC_REGNUM: return(USE_SHADOW_PC ? (21) : (11));
1271 case PC2_REGNUM: return(USE_SHADOW_PC ? (22) : (12));
1272 case MMU_REGNUM: return(13);
1273 case LRU_REGNUM: return(14);
1274 case IPC_REGNUM: return(128);
1275 case IPA_REGNUM: return(129);
1276 case IPB_REGNUM: return(130);
1277 case Q_REGNUM: return(131);
1278 case ALU_REGNUM: return(132);
1279 case BP_REGNUM: return(133);
1280 case FC_REGNUM: return(134);
1281 case CR_REGNUM: return(135);
1282 case FPE_REGNUM: return(160);
1283 case INTE_REGNUM: return(161);
1284 case FPS_REGNUM: return(162);
1285 case EXO_REGNUM:return(164);
1287 return(255); /* Failure ? */
1290 /****************************************************************************/
1292 * Determine the Target memory space qualifier based on the addr.
1293 * FIXME: Can't distinguis I_ROM/D_ROM.
1294 * FIXME: Doesn't know anything about I_CACHE/D_CACHE.
1297 udi_memory_space(addr)
1300 UDIUInt32 tstart = IMemStart;
1301 UDIUInt32 tend = tstart + IMemSize;
1302 UDIUInt32 dstart = DMemStart;
1303 UDIUInt32 dend = tstart + DMemSize;
1304 UDIUInt32 rstart = RMemStart;
1305 UDIUInt32 rend = tstart + RMemSize;
1307 if (((UDIUInt32)addr >= tstart) && ((UDIUInt32)addr < tend)) {
1308 return UDI29KIRAMSpace;
1309 } else if (((UDIUInt32)addr >= dstart) && ((UDIUInt32)addr < dend)) {
1310 return UDI29KDRAMSpace;
1311 } else if (((UDIUInt32)addr >= rstart) && ((UDIUInt32)addr < rend)) {
1312 /* FIXME: how do we determine between D_ROM and I_ROM */
1313 return UDI29KIROMSpace;
1314 } else /* FIXME: what do me do now? */
1315 return UDI29KDRAMSpace; /* Hmmm! */
1317 /*********************************************************************** STUBS
1320 void convert16() {;}
1321 void convert32() {;}
1322 FILE* EchoFile = 0; /* used for debugging */
1323 int QuietMode = 0; /* used for debugging */
1325 /****************************************************************************/
1327 * Define the target subroutine names
1329 static struct target_ops udi_ops = {
1330 "udi", "Remote UDI connected TIP",
1331 "Remote debug an AMD 29k using UDI socket connection to TIP process",
1332 udi_open, udi_close,
1333 udi_attach, udi_detach, udi_resume, udi_wait,
1334 udi_fetch_registers, udi_store_registers,
1335 udi_prepare_to_store,
1336 udi_xfer_inferior_memory,
1338 udi_insert_breakpoint, udi_remove_breakpoint, /* Breakpoints */
1339 0, 0, 0, 0, 0, /* Terminal handling */
1340 udi_kill, /* FIXME, kill */
1342 0, /* lookup_symbol */
1343 udi_create_inferior, /* create_inferior */
1344 udi_mourn, /* mourn_inferior FIXME */
1345 process_stratum, 0, /* next */
1346 1, 1, 1, 1, 1, /* all mem, mem, stack, regs, exec */
1347 0, 0, /* Section pointers */
1348 OPS_MAGIC, /* Always the last thing */
1351 void _initialize_remote_udi()
1353 add_target (&udi_ops);
1356 #ifdef NO_HIF_SUPPORT
1360 return(0); /* Emulate a failure */