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.
29 file to gdb 3.95. I was unable to get this working on sun3os4
30 with termio, only with sgtty.
31 - Daniel Mann at AMD took the 3.95 adaptions above and replaced
32 MiniMON interface with UDI-p interface. */
45 #include "29k-share/udi/udiproc.h"
48 #include "gdbcore.h" /* For download function */
50 /* access the register store directly, without going through
51 the normal handler functions. This avoids an extra data copy. */
53 extern int stop_soon_quietly; /* for wait_for_inferior */
54 extern struct value *call_function_by_hand();
55 static void udi_resume PARAMS ((int pid, int step, enum target_signal sig));
56 static void udi_fetch_registers PARAMS ((int regno));
57 static void udi_load PARAMS ((char *args, int from_tty));
58 static void fetch_register PARAMS ((int regno));
59 static void udi_store_registers PARAMS ((int regno));
60 static int store_register PARAMS ((int regno));
61 static int regnum_to_srnum PARAMS ((int regno));
62 static void udi_close PARAMS ((int quitting));
63 static CPUSpace udi_memory_space PARAMS ((CORE_ADDR addr));
64 static int udi_write_inferior_memory PARAMS ((CORE_ADDR memaddr, char *myaddr,
66 static int udi_read_inferior_memory PARAMS ((CORE_ADDR memaddr, char *myaddr,
68 static void download PARAMS ((char *load_arg_string, int from_tty));
69 char CoffFileName[100] = "";
71 #define FREEZE_MODE (read_register(CPS_REGNUM) & 0x400)
72 #define USE_SHADOW_PC ((processor_type == a29k_freeze_mode) && FREEZE_MODE)
74 static int timeout = 5;
75 extern struct target_ops udi_ops; /* Forward declaration */
77 /* Special register enumeration.
80 /******************************************************************* UDI DATA*/
81 #define MAXDATA 2*1024 /* max UDI[read/write] byte size */
82 /* Descriptor for I/O to remote machine. Initialize it to -1 so that
83 udi_open knows that we don't have a file open when the program
86 UDISessionId udi_session_id = -1;
87 static char *udi_config_id;
89 CPUOffset IMemStart = 0;
90 CPUSizeT IMemSize = 0;
91 CPUOffset DMemStart = 0;
92 CPUSizeT DMemSize = 0;
93 CPUOffset RMemStart = 0;
94 CPUSizeT RMemSize = 0;
98 UDIMemoryRange address_ranges[2]; /* Text and data */
99 UDIResource entry = {0, 0}; /* Entry point */
100 CPUSizeT stack_sizes[2]; /* Regular and memory stacks */
102 #define SBUF_MAX 1024 /* maximum size of string handling buffer */
105 typedef struct bkpt_entry_str
110 unsigned int BreakId;
112 #define BKPT_TABLE_SIZE 40
113 static bkpt_entry_t bkpt_table[BKPT_TABLE_SIZE];
114 extern char dfe_errmsg[]; /* error string */
116 /* malloc'd name of the program on the remote system. */
117 static char *prog_name = NULL;
119 /* This is called not only when we first attach, but also when the
120 user types "run" after having attached. */
123 udi_create_inferior (execfile, args, env)
132 if (prog_name != NULL)
134 prog_name = savestring (execfile, strlen (execfile));
136 else if (entry.Offset)
139 error ("No image loaded into target.");
141 if (udi_session_id < 0)
143 /* If the TIP is not open, open it. */
144 if (UDIConnect (udi_config_id, &udi_session_id))
145 error("UDIConnect() failed: %s\n", dfe_errmsg);
146 /* We will need to download the program. */
150 inferior_pid = 40000;
153 download(execfile, 0);
155 args1 = alloca (strlen(execfile) + strlen(args) + 2);
157 if (execfile[0] == '\0')
159 /* It is empty. We need to quote it somehow, or else the target
160 will think there is no argument being passed here. According
161 to the UDI spec it is quoted "according to TIP OS rules" which
162 I guess means quoting it like the Unix shell should work
163 (sounds pretty bogus to me...). In fact it doesn't work (with
164 isstip anyway), but passing in two quotes as the argument seems
165 like a reasonable enough behavior anyway (I guess). */
167 strcpy (args1, "''");
169 strcpy (args1, execfile);
171 strcat (args1, args);
173 UDIInitializeProcess (address_ranges, /* ProcessMemory[] */
174 (UDIInt)2, /* NumberOfRanges */
175 entry, /* EntryPoint */
176 stack_sizes, /* *StackSizes */
177 (UDIInt)2, /* NumberOfStacks */
178 args1); /* ArgString */
180 init_wait_for_inferior ();
181 clear_proceed_status ();
182 proceed (-1, TARGET_SIGNAL_DEFAULT, 0);
189 /* Requiring "target udi" each time you run is a major pain. I suspect
190 this was just blindy copied from remote.c, in which "target" and
191 "run" are combined. Having a udi target without an inferior seems
192 to work between "target udi" and "run", so why not now? */
193 pop_target (); /* Pop back to no-child state */
195 /* But if we're going to want to run it again, we better remove the
197 remove_breakpoints ();
198 generic_mourn_inferior ();
201 /******************************************************************** UDI_OPEN
202 ** Open a connection to remote TIP.
203 NAME is the socket domain used for communication with the TIP,
204 then a space and the socket name or TIP-host name.
205 '<udi_udi_config_id>' for example.
208 /* XXX - need cleanups for udiconnect for various failures!!! */
211 udi_open (name, from_tty)
218 UDIMemoryRange KnownMemory[10];
219 UDIUInt32 ChipVersions[10];
220 UDIInt NumberOfRanges = 10;
221 UDIInt NumberOfChips = 10;
223 UDIUInt32 TIPId, TargetId, DFEId, DFE, TIP, DFEIPCId, TIPIPCId;
225 target_preopen(from_tty);
229 for (cnt = 0; cnt < BKPT_TABLE_SIZE; cnt++)
230 bkpt_table[cnt].Type = 0;
233 free (udi_config_id);
236 error("Usage: target udi config_id, where config_id appears in udi_soc file");
238 udi_config_id = strdup (strtok (name, " \t"));
240 if (UDIConnect (udi_config_id, &udi_session_id))
241 /* FIXME: Should set udi_session_id to -1 here. */
242 error("UDIConnect() failed: %s\n", dfe_errmsg);
244 push_target (&udi_ops);
247 ** Initialize target configuration structure (global)
249 if (UDIGetTargetConfig (KnownMemory, &NumberOfRanges,
250 ChipVersions, &NumberOfChips))
251 error ("UDIGetTargetConfig() failed");
252 if (NumberOfChips > 2)
253 fprintf_unfiltered(gdb_stderr,"Target has more than one processor\n");
254 for (cnt=0; cnt < NumberOfRanges; cnt++)
256 switch(KnownMemory[cnt].Space)
259 fprintf_unfiltered(gdb_stderr, "UDIGetTargetConfig() unknown memory space\n");
263 case UDI29KIROMSpace:
264 RMemStart = KnownMemory[cnt].Offset;
265 RMemSize = KnownMemory[cnt].Size;
267 case UDI29KIRAMSpace:
268 IMemStart = KnownMemory[cnt].Offset;
269 IMemSize = KnownMemory[cnt].Size;
271 case UDI29KDRAMSpace:
272 DMemStart = KnownMemory[cnt].Offset;
273 DMemSize = KnownMemory[cnt].Size;
278 a29k_get_processor_type ();
280 if (UDICreateProcess (&PId))
281 fprintf_unfiltered(gdb_stderr, "UDICreateProcess() failed\n");
283 /* Print out some stuff, letting the user now what's going on */
284 if (UDICapabilities (&TIPId, &TargetId, DFEId, DFE, &TIP, &DFEIPCId,
286 error ("UDICapabilities() failed");
289 printf_filtered ("Connected via UDI socket,\n\
290 DFE-IPC version %x.%x.%x TIP-IPC version %x.%x.%x TIP version %x.%x.%x\n %s\n",
291 (DFEIPCId>>8)&0xf, (DFEIPCId>>4)&0xf, DFEIPCId&0xf,
292 (TIPIPCId>>8)&0xf, (TIPIPCId>>4)&0xf, TIPIPCId&0xf,
293 (TargetId>>8)&0xf, (TargetId>>4)&0xf, TargetId&0xf,
298 /******************************************************************* UDI_CLOSE
299 Close the open connection to the TIP process.
300 Use this when you want to detach and do something else
303 udi_close (quitting) /*FIXME: how is quitting used */
306 if (udi_session_id < 0)
309 /* We should never get here if there isn't something valid in
312 if (UDIDisconnect (udi_session_id, UDITerminateSession))
315 warning ("UDIDisconnect() failed in udi_close");
317 error ("UDIDisconnect() failed in udi_close");
320 /* Do not try to close udi_session_id again, later in the program. */
324 printf_filtered (" Ending remote debugging\n");
327 /**************************************************************** UDI_ATACH */
328 /* Attach to a program that is already loaded and running
329 * Upon exiting the process's execution is stopped.
332 udi_attach (args, from_tty)
341 UDIBool HostEndian = 0;
345 error_no_arg ("program to attach");
347 if (udi_session_id < 0)
348 error ("UDI connection not opened yet, use the 'target udi' command.\n");
351 printf_unfiltered ("Attaching to remote program %s...\n", prog_name);
354 From.Space = UDI29KSpecialRegs;
356 if (err = UDIRead(From, &PC_adds, Count, Size, &CountDone, HostEndian))
357 error ("UDIRead failed in udi_attach");
358 printf_unfiltered ("Remote process is now halted, pc1 = 0x%x.\n", PC_adds);
360 /************************************************************* UDI_DETACH */
361 /* Terminate the open connection to the TIP process.
362 Use this when you want to detach and do something else
363 with your gdb. Leave remote process running (with no breakpoints set). */
365 udi_detach (args,from_tty)
370 remove_breakpoints(); /* Just in case there were any left in */
372 if (UDIDisconnect (udi_session_id, UDIContinueSession))
373 error ("UDIDisconnect() failed in udi_detach");
375 /* Don't try to UDIDisconnect it again in udi_close, which is called from
383 printf_unfiltered ("Detaching from TIP\n");
387 /****************************************************************** UDI_RESUME
388 ** Tell the remote machine to resume. */
391 udi_resume (pid, step, sig)
393 enum target_signal sig;
397 UDIStepType StepType = UDIStepNatural;
400 if (step) /* step 1 instruction */
402 tip_error = UDIStep (Steps, StepType, Range);
406 fprintf_unfiltered (gdb_stderr, "UDIStep() error = %d\n", tip_error);
407 error ("failed in udi_resume");
411 error ("UDIExecute() failed in udi_resume");
414 /******************************************************************** UDI_WAIT
415 ** Wait until the remote machine stops, then return,
416 storing status in STATUS just as `wait' would. */
419 udi_wait (pid, status)
421 struct target_waitstatus *status;
427 int old_timeout = timeout;
428 int old_immediate_quit = immediate_quit;
431 status->kind = TARGET_WAITKIND_EXITED;
432 status->value.integer = 0;
434 /* wait for message to arrive. It should be:
435 If the target stops executing, udi_wait() should return.
437 timeout = 0; /* Wait indefinetly for a message */
438 immediate_quit = 1; /* Helps ability to QUIT */
443 MaxTime = UDIWaitForever;
444 UDIWait(MaxTime, &PId, &StopReason);
445 QUIT; /* Let user quit if they want */
447 switch (StopReason & UDIGrossState)
450 if (UDIGetStdout (sbuf, (UDISizeT)SBUF_MAX, &CountDone))
451 /* This is said to happen if the program tries to output
452 a whole bunch of output (more than SBUF_MAX, I would
453 guess). It doesn't seem to happen with the simulator. */
454 warning ("UDIGetStdout() failed in udi_wait");
455 fwrite (sbuf, 1, CountDone, gdb_stdout);
456 gdb_flush(gdb_stdout);
460 UDIGetStderr (sbuf, (UDISizeT)SBUF_MAX, &CountDone);
461 fwrite (sbuf, 1, CountDone, gdb_stderr);
462 gdb_flush(gdb_stderr);
475 } while (i < SBUF_MAX && ch != '\n');
476 UDIPutStdin (sbuf, (UDISizeT)i, &CountDone);
481 /* In spite of the fact that we told UDIWait to wait forever, it will
482 return spuriously sometimes. */
491 switch (StopReason & UDIGrossState)
494 printf_unfiltered("Am290*0 received vector number %d\n", StopReason >> 24);
496 switch (StopReason >> 8)
498 case 0: /* Illegal opcode */
499 printf_unfiltered(" (break point)\n");
500 status->kind = TARGET_WAITKIND_STOPPED;
501 status->value.sig = TARGET_SIGNAL_TRAP;
503 case 1: /* Unaligned Access */
504 status->kind = TARGET_WAITKIND_STOPPED;
505 status->value.sig = TARGET_SIGNAL_BUS;
509 status->kind = TARGET_WAITKIND_STOPPED;
510 status->value.sig = TARGET_SIGNAL_FPE;
512 case 5: /* Protection Violation */
513 status->kind = TARGET_WAITKIND_STOPPED;
514 /* Why not SEGV? What is a Protection Violation? */
515 status->value.sig = TARGET_SIGNAL_ILL;
519 case 8: /* User Instruction Mapping Miss */
520 case 9: /* User Data Mapping Miss */
521 case 10: /* Supervisor Instruction Mapping Miss */
522 case 11: /* Supervisor Data Mapping Miss */
523 status->kind = TARGET_WAITKIND_STOPPED;
524 status->value.sig = TARGET_SIGNAL_SEGV;
528 status->kind = TARGET_WAITKIND_STOPPED;
529 status->value.sig = TARGET_SIGNAL_ILL;
532 status->kind = TARGET_WAITKIND_STOPPED;
533 status->value.sig = TARGET_SIGNAL_ALRM;
536 status->kind = TARGET_WAITKIND_STOPPED;
537 status->value.sig = TARGET_SIGNAL_TRAP;
542 case 19: /* INTR3/Internal */
545 status->kind = TARGET_WAITKIND_STOPPED;
546 status->value.sig = TARGET_SIGNAL_INT;
548 case 22: /* Floating-Point Exception */
549 status->kind = TARGET_WAITKIND_STOPPED;
551 status->value.sig = TARGET_SIGNAL_ILL;
553 case 77: /* assert 77 */
554 status->kind = TARGET_WAITKIND_STOPPED;
555 status->value.sig = TARGET_SIGNAL_TRAP;
558 status->kind = TARGET_WAITKIND_EXITED;
559 status->value.integer = 0;
562 case UDINotExecuting:
563 status->kind = TARGET_WAITKIND_STOPPED;
564 status->value.sig = TARGET_SIGNAL_TERM;
567 status->kind = TARGET_WAITKIND_STOPPED;
568 status->value.sig = TARGET_SIGNAL_TSTP;
571 status->kind = TARGET_WAITKIND_STOPPED;
572 status->value.sig = TARGET_SIGNAL_URG;
576 status->kind = TARGET_WAITKIND_STOPPED;
577 status->value.sig = TARGET_SIGNAL_TRAP;
580 status->kind = TARGET_WAITKIND_STOPPED;
581 status->value.sig = TARGET_SIGNAL_STOP;
584 status->kind = TARGET_WAITKIND_STOPPED;
585 status->value.sig = TARGET_SIGNAL_KILL;
589 status->kind = TARGET_WAITKIND_EXITED;
590 status->value.integer = 0;
593 timeout = old_timeout; /* Restore original timeout value */
594 immediate_quit = old_immediate_quit;
599 /* Handy for debugging */
607 UDIBool HostEndian = 0;
610 unsigned long myregs[256];
613 From.Space = UDI29KPC;
615 To = (UDIUInt32 *)pc;
618 err = UDIRead(From, To, Count, Size, &CountDone, HostEndian);
620 printf_unfiltered ("err = %d, CountDone = %d, pc[0] = 0x%x, pc[1] = 0x%x\n",
621 err, CountDone, pc[0], pc[1]);
623 udi_fetch_registers(-1);
625 printf_unfiltered("other pc1 = 0x%x, pc0 = 0x%x\n", *(int *)®isters[4 * PC_REGNUM],
626 *(int *)®isters[4 * NPC_REGNUM]);
628 /* Now, read all the registers globally */
630 From.Space = UDI29KGlobalRegs;
632 err = UDIRead(From, myregs, 256, 4, &CountDone, HostEndian);
634 printf ("err = %d, CountDone = %d\n", err, CountDone);
638 for (i = 0; i < 256; i += 2)
639 printf("%d:\t%#10x\t%11d\t%#10x\t%11d\n", i, myregs[i], myregs[i],
640 myregs[i+1], myregs[i+1]);
647 /********************************************************** UDI_FETCH_REGISTERS
648 * Read a remote register 'regno'.
649 * If regno==-1 then read all the registers.
652 udi_fetch_registers (regno)
660 UDIBool HostEndian = 0;
665 fetch_register(regno);
671 From.Space = UDI29KGlobalRegs;
673 To = (UDIUInt32 *)®isters[4 * GR1_REGNUM];
675 if (err = UDIRead(From, To, Count, Size, &CountDone, HostEndian))
676 error("UDIRead() failed in udi_fetch_registers");
678 register_valid[GR1_REGNUM] = 1;
680 #if defined(GR64_REGNUM) /* Read gr64-127 */
682 /* Global Registers gr64-gr95 */
684 From.Space = UDI29KGlobalRegs;
686 To = (UDIUInt32 *)®isters[4 * GR64_REGNUM];
688 if (err = UDIRead(From, To, Count, Size, &CountDone, HostEndian))
689 error("UDIRead() failed in udi_fetch_registers");
691 for (i = GR64_REGNUM; i < GR64_REGNUM + 32; i++)
692 register_valid[i] = 1;
694 #endif /* GR64_REGNUM */
696 /* Global Registers gr96-gr127 */
698 From.Space = UDI29KGlobalRegs;
700 To = (UDIUInt32 *)®isters[4 * GR96_REGNUM];
702 if (err = UDIRead(From, To, Count, Size, &CountDone, HostEndian))
703 error("UDIRead() failed in udi_fetch_registers");
705 for (i = GR96_REGNUM; i < GR96_REGNUM + 32; i++)
706 register_valid[i] = 1;
708 /* Local Registers */
710 From.Space = UDI29KLocalRegs;
712 To = (UDIUInt32 *)®isters[4 * LR0_REGNUM];
714 if (err = UDIRead(From, To, Count, Size, &CountDone, HostEndian))
715 error("UDIRead() failed in udi_fetch_registers");
717 for (i = LR0_REGNUM; i < LR0_REGNUM + 128; i++)
718 register_valid[i] = 1;
720 /* Protected Special Registers */
722 From.Space = UDI29KSpecialRegs;
724 To = (UDIUInt32 *)®isters[4 * SR_REGNUM(0)];
726 if (err = UDIRead(From, To, Count, Size, &CountDone, HostEndian))
727 error("UDIRead() failed in udi_fetch_registers");
729 for (i = SR_REGNUM(0); i < SR_REGNUM(0) + 15; i++)
730 register_valid[i] = 1;
732 if (USE_SHADOW_PC) { /* Let regno_to_srnum() handle the register number */
733 fetch_register(NPC_REGNUM);
734 fetch_register(PC_REGNUM);
735 fetch_register(PC2_REGNUM);
737 /* Unprotected Special Registers sr128-sr135 */
739 From.Space = UDI29KSpecialRegs;
741 To = (UDIUInt32 *)®isters[4 * SR_REGNUM(128)];
743 if (err = UDIRead(From, To, Count, Size, &CountDone, HostEndian))
744 error("UDIRead() failed in udi_fetch_registers");
746 for (i = SR_REGNUM(128); i < SR_REGNUM(128) + 135-128+1; i++)
747 register_valid[i] = 1;
752 printf_unfiltered("Fetching all registers\n");
753 printf_unfiltered("Fetching PC0 = 0x%x, PC1 = 0x%x, PC2 = 0x%x\n",
754 read_register(NPC_REGNUM), read_register(PC_REGNUM),
755 read_register(PC2_REGNUM));
758 /* There doesn't seem to be any way to get these. */
761 supply_register (FPE_REGNUM, (char *) &val);
762 supply_register (INTE_REGNUM, (char *) &val);
763 supply_register (FPS_REGNUM, (char *) &val);
764 supply_register (EXO_REGNUM, (char *) &val);
769 /********************************************************* UDI_STORE_REGISTERS
770 ** Store register regno into the target.
771 * If regno==-1 then store all the registers.
775 udi_store_registers (regno)
783 UDIBool HostEndian = 0;
787 store_register(regno);
793 printf_unfiltered("Storing all registers\n");
794 printf_unfiltered("PC0 = 0x%x, PC1 = 0x%x, PC2 = 0x%x\n", read_register(NPC_REGNUM),
795 read_register(PC_REGNUM), read_register(PC2_REGNUM));
800 From = (UDIUInt32 *)®isters[4 * GR1_REGNUM];
801 To.Space = UDI29KGlobalRegs;
804 if(UDIWrite(From, To, Count, Size, &CountDone, HostEndian))
805 error("UDIWrite() failed in udi_store_regisetrs");
807 #if defined(GR64_REGNUM)
809 /* Global registers gr64-gr95 */
811 From = (UDIUInt32 *)®isters[4 * GR64_REGNUM];
812 To.Space = UDI29KGlobalRegs;
815 if(UDIWrite(From, To, Count, Size, &CountDone, HostEndian))
816 error("UDIWrite() failed in udi_store_regisetrs");
818 #endif /* GR64_REGNUM */
820 /* Global registers gr96-gr127 */
822 From = (UDIUInt32 *)®isters[4 * GR96_REGNUM];
823 To.Space = UDI29KGlobalRegs;
826 if(UDIWrite(From, To, Count, Size, &CountDone, HostEndian))
827 error("UDIWrite() failed in udi_store_regisetrs");
829 /* Local Registers */
831 From = (UDIUInt32 *)®isters[4 * LR0_REGNUM];
832 To.Space = UDI29KLocalRegs;
835 if(UDIWrite(From, To, Count, Size, &CountDone, HostEndian))
836 error("UDIWrite() failed in udi_store_regisetrs");
839 /* Protected Special Registers */ /* VAB through TMR */
841 From = (UDIUInt32 *)®isters[4 * SR_REGNUM(0)];
842 To.Space = UDI29KSpecialRegs;
845 if(UDIWrite(From, To, Count, Size, &CountDone, HostEndian))
846 error("UDIWrite() failed in udi_store_regisetrs");
848 /* PC0, PC1, PC2 possibly as shadow registers */
850 From = (UDIUInt32 *)®isters[4 * SR_REGNUM(10)];
851 To.Space = UDI29KSpecialRegs;
854 To.Offset = 20; /* SPC0 */
856 To.Offset = 10; /* PC0 */
857 if(UDIWrite(From, To, Count, Size, &CountDone, HostEndian))
858 error("UDIWrite() failed in udi_store_regisetrs");
860 /* PC1 via UDI29KPC */
862 From = (UDIUInt32 *)®isters[4 * PC_REGNUM];
864 To.Offset = 0; /* PC1 */
866 if (UDIWrite (From, To, Count, Size, &CountDone, HostEndian))
867 error ("UDIWrite() failed in udi_store_regisetrs");
871 From = (UDIUInt32 *)®isters[4 * SR_REGNUM(13)];
872 To.Space = UDI29KSpecialRegs;
875 if(UDIWrite(From, To, Count, Size, &CountDone, HostEndian))
876 error("UDIWrite() failed in udi_store_regisetrs");
878 /* Unprotected Special Registers */
880 From = (UDIUInt32 *)®isters[4 * SR_REGNUM(128)];
881 To.Space = UDI29KSpecialRegs;
884 if(UDIWrite(From, To, Count, Size, &CountDone, HostEndian))
885 error("UDIWrite() failed in udi_store_regisetrs");
887 registers_changed ();
890 /****************************************************** UDI_PREPARE_TO_STORE */
891 /* Get ready to modify the registers array. On machines which store
892 individual registers, this doesn't need to do anything. On machines
893 which store all the registers in one fell swoop, this makes sure
894 that registers contains all the registers from the program being
898 udi_prepare_to_store ()
900 /* Do nothing, since we can store individual regs */
903 /********************************************************** TRANSLATE_ADDR */
908 #if defined(ULTRA3) && defined(KERNEL_DEBUGGING)
909 /* Check for a virtual address in the kernel */
910 /* Assume physical address of ublock is in paddr_u register */
911 /* FIXME: doesn't work for user virtual addresses */
912 if (addr >= UVADDR) {
913 /* PADDR_U register holds the physical address of the ublock */
914 CORE_ADDR i = (CORE_ADDR)read_register(PADDR_U_REGNUM);
915 return(i + addr - (CORE_ADDR)UVADDR);
923 /************************************************* UDI_XFER_INFERIOR_MEMORY */
924 /* FIXME! Merge these two. */
926 udi_xfer_inferior_memory (memaddr, myaddr, len, write)
933 memaddr = translate_addr(memaddr);
936 return udi_write_inferior_memory (memaddr, myaddr, len);
938 return udi_read_inferior_memory (memaddr, myaddr, len);
941 /********************************************************** UDI_FILES_INFO */
945 printf_unfiltered ("\tAttached to UDI socket to %s", udi_config_id);
946 if (prog_name != NULL)
947 printf_unfiltered ("and running program %s", prog_name);
948 printf_unfiltered (".\n");
951 /**************************************************** UDI_INSERT_BREAKPOINT */
953 udi_insert_breakpoint (addr, contents_cache)
955 char *contents_cache;
960 for (cnt = 0; cnt < BKPT_TABLE_SIZE; cnt++)
961 if (bkpt_table[cnt].Type == 0) /* Find first free slot */
964 if(cnt >= BKPT_TABLE_SIZE)
965 error("Too many breakpoints set");
967 bkpt_table[cnt].Addr.Offset = addr;
968 bkpt_table[cnt].Addr.Space = UDI29KIRAMSpace;
969 bkpt_table[cnt].PassCount = 1;
970 bkpt_table[cnt].Type = UDIBreakFlagExecute;
972 err = UDISetBreakpoint(bkpt_table[cnt].Addr,
973 bkpt_table[cnt].PassCount,
974 bkpt_table[cnt].Type,
975 &bkpt_table[cnt].BreakId);
977 if (err == 0) return 0; /* Success */
979 bkpt_table[cnt].Type = 0;
980 error("UDISetBreakpoint returned error code %d\n", err);
983 /**************************************************** UDI_REMOVE_BREAKPOINT */
985 udi_remove_breakpoint (addr, contents_cache)
987 char *contents_cache;
992 for (cnt = 0; cnt < BKPT_TABLE_SIZE; cnt++)
993 if (bkpt_table[cnt].Addr.Offset == addr) /* Find matching breakpoint */
996 if(cnt >= BKPT_TABLE_SIZE)
997 error("Can't find breakpoint in table");
999 bkpt_table[cnt].Type = 0;
1001 err = UDIClearBreakpoint(bkpt_table[cnt].BreakId);
1002 if (err == 0) return 0; /* Success */
1004 error("UDIClearBreakpoint returned error code %d\n", err);
1008 udi_kill(arg,from_tty)
1015 UDIStop does not really work as advertised. It causes the TIP to close it's
1016 connection, which usually results in GDB dying with a SIGPIPE. For now, we
1017 just invoke udi_close, which seems to get things right.
1021 udi_session_id = -1;
1025 printf_unfiltered("Target has been stopped.");
1032 /* Keep the target around, e.g. so "run" can do the right thing when
1033 we are already debugging something. */
1035 if (UDIDisconnect (udi_session_id, UDITerminateSession))
1037 warning ("UDIDisconnect() failed");
1040 /* Do not try to close udi_session_id again, later in the program. */
1041 udi_session_id = -1;
1046 Load a program into the target. Args are: `program {options}'. The options
1047 are used to control loading of the program, and are NOT passed onto the
1048 loaded code as arguments. (You need to use the `run' command to do that.)
1051 -ms %d Set mem stack size to %d
1052 -rs %d Set regular stack size to %d
1053 -i send init info (default)
1054 -noi don't send init info
1055 -[tT] Load Text section
1056 -[dD] Load Data section
1057 -[bB] Load BSS section
1058 -[lL] Load Lit section
1062 download(load_arg_string, from_tty)
1063 char *load_arg_string;
1066 #define DEFAULT_MEM_STACK_SIZE 0x6000
1067 #define DEFAULT_REG_STACK_SIZE 0x2000
1074 int load_text = 1, load_data = 1, load_bss = 1, load_lit = 1;
1076 address_ranges[0].Space = UDI29KIRAMSpace;
1077 address_ranges[0].Offset = 0xffffffff;
1078 address_ranges[0].Size = 0;
1080 address_ranges[1].Space = UDI29KDRAMSpace;
1081 address_ranges[1].Offset = 0xffffffff;
1082 address_ranges[1].Size = 0;
1084 stack_sizes[0] = DEFAULT_REG_STACK_SIZE;
1085 stack_sizes[1] = DEFAULT_MEM_STACK_SIZE;
1089 filename = strtok(load_arg_string, " \t");
1091 error ("Must specify at least a file name with the load command");
1093 filename = tilde_expand (filename);
1094 make_cleanup (free, filename);
1096 while (token = strtok (NULL, " \t"))
1098 if (token[0] == '-')
1102 if (STREQ (token, "ms"))
1103 stack_sizes[1] = atol (strtok (NULL, " \t"));
1104 else if (STREQ (token, "rs"))
1105 stack_sizes[0] = atol (strtok (NULL, " \t"));
1108 load_text = load_data = load_bss = load_lit = 0;
1131 error ("Unknown UDI load option -%s", token-1);
1138 pbfd = bfd_openr (filename, gnutarget);
1141 perror_with_name (filename);
1143 make_cleanup (bfd_close, pbfd);
1148 if (!bfd_check_format (pbfd, bfd_object))
1149 error ("It doesn't seem to be an object file");
1151 for (section = pbfd->sections; section; section = section->next)
1153 if (bfd_get_section_flags (pbfd, section) & SEC_ALLOC)
1157 unsigned long section_size, section_end;
1158 const char *section_name;
1160 section_name = bfd_get_section_name (pbfd, section);
1161 if (STREQ (section_name, ".text") && !load_text)
1163 else if (STREQ (section_name, ".data") && !load_data)
1165 else if (STREQ (section_name, ".bss") && !load_bss)
1167 else if (STREQ (section_name, ".lit") && !load_lit)
1170 To.Offset = bfd_get_section_vma (pbfd, section);
1171 section_size = bfd_section_size (pbfd, section);
1172 section_end = To.Offset + section_size;
1174 if (section_size == 0)
1175 /* This is needed at least in the BSS case, where the code
1176 below starts writing before it even checks the size. */
1179 printf_unfiltered("[Loading section %s at %x (%d bytes)]\n",
1184 if (bfd_get_section_flags (pbfd, section) & SEC_CODE)
1186 To.Space = UDI29KIRAMSpace;
1188 address_ranges[0].Offset = min (address_ranges[0].Offset,
1190 address_ranges[0].Size = max (address_ranges[0].Size,
1192 - address_ranges[0].Offset);
1196 To.Space = UDI29KDRAMSpace;
1198 address_ranges[1].Offset = min (address_ranges[1].Offset,
1200 address_ranges[1].Size = max (address_ranges[1].Size,
1202 - address_ranges[1].Offset);
1205 if (bfd_get_section_flags (pbfd, section) & SEC_LOAD) /* Text, data or lit */
1211 while (section_size > 0)
1215 Count = min (section_size, 1024);
1217 bfd_get_section_contents (pbfd, section, buffer, fptr,
1220 err = UDIWrite ((UDIHostMemPtr)buffer, /* From */
1223 (UDISizeT)1, /* Size */
1224 &Count, /* CountDone */
1225 (UDIBool)0); /* HostEndian */
1227 error ("UDIWrite failed, error = %d", err);
1231 section_size -= Count;
1237 unsigned long zero = 0;
1239 /* Write a zero byte at the vma */
1240 /* FIXME: Broken for sections of 1-3 bytes (we test for
1242 err = UDIWrite ((UDIHostMemPtr)&zero, /* From */
1244 (UDICount)1, /* Count */
1245 (UDISizeT)4, /* Size */
1246 &Count, /* CountDone */
1247 (UDIBool)0); /* HostEndian */
1249 error ("UDIWrite failed, error = %d", err);
1254 /* Now, duplicate it for the length of the BSS */
1255 err = UDICopy (From, /* From */
1257 (UDICount)(section_size/4 - 1), /* Count */
1258 (UDISizeT)4, /* Size */
1259 &Count, /* CountDone */
1260 (UDIBool)1); /* Direction */
1266 xerr = UDIGetErrorMsg(err, 100, message, &Count);
1268 fprintf_unfiltered (gdb_stderr, "Error is %s\n", message);
1270 fprintf_unfiltered (gdb_stderr, "xerr is %d\n", xerr);
1271 error ("UDICopy failed, error = %d", err);
1278 entry.Space = UDI29KIRAMSpace;
1279 entry.Offset = bfd_get_start_address (pbfd);
1284 /* User interface to download an image into the remote target. See download()
1285 * for details on args.
1289 udi_load(args, from_tty)
1293 download (args, from_tty);
1295 symbol_file_add (strtok (args, " \t"), from_tty, 0, 0, 0, 0);
1298 /*************************************************** UDI_WRITE_INFERIOR_MEMORY
1299 ** Copy LEN bytes of data from debugger memory at MYADDR
1300 to inferior's memory at MEMADDR. Returns number of bytes written. */
1302 udi_write_inferior_memory (memaddr, myaddr, len)
1312 UDICount CountDone = 0;
1313 UDIBool HostEndian = 0;
1315 To.Space = udi_memory_space(memaddr);
1316 From = (UDIUInt32*)myaddr;
1318 while (nwritten < len)
1319 { Count = len - nwritten;
1320 if (Count > MAXDATA) Count = MAXDATA;
1321 To.Offset = memaddr + nwritten;
1322 if(UDIWrite(From, To, Count, Size, &CountDone, HostEndian))
1323 { error("UDIWrite() failed in udi_write_inferrior_memory");
1327 { nwritten += CountDone;
1334 /**************************************************** UDI_READ_INFERIOR_MEMORY
1335 ** Read LEN bytes from inferior memory at MEMADDR. Put the result
1336 at debugger address MYADDR. Returns number of bytes read. */
1338 udi_read_inferior_memory(memaddr, myaddr, len)
1348 UDICount CountDone = 0;
1349 UDIBool HostEndian = 0;
1352 From.Space = udi_memory_space(memaddr);
1353 To = (UDIUInt32*)myaddr;
1356 { Count = len - nread;
1357 if (Count > MAXDATA) Count = MAXDATA;
1358 From.Offset = memaddr + nread;
1359 if(err = UDIRead(From, To, Count, Size, &CountDone, HostEndian))
1360 { error("UDIRead() failed in udi_read_inferrior_memory");
1364 { nread += CountDone;
1371 /********************************************************************* WARNING
1376 error ("ERROR while loading program into remote TIP: $d\n", num);
1380 /*****************************************************************************/
1381 /* Fetch a single register indicatated by 'regno'.
1382 * Returns 0/-1 on success/failure.
1385 fetch_register (regno)
1393 UDIBool HostEndian = 0;
1397 if (regno == GR1_REGNUM)
1399 From.Space = UDI29KGlobalRegs;
1402 else if (regno >= GR96_REGNUM && regno < GR96_REGNUM + 32)
1404 From.Space = UDI29KGlobalRegs;
1405 From.Offset = (regno - GR96_REGNUM) + 96;;
1408 #if defined(GR64_REGNUM)
1410 else if (regno >= GR64_REGNUM && regno < GR64_REGNUM + 32 )
1412 From.Space = UDI29KGlobalRegs;
1413 From.Offset = (regno - GR64_REGNUM) + 64;
1416 #endif /* GR64_REGNUM */
1418 else if (regno >= LR0_REGNUM && regno < LR0_REGNUM + 128)
1420 From.Space = UDI29KLocalRegs;
1421 From.Offset = (regno - LR0_REGNUM);
1423 else if (regno>=FPE_REGNUM && regno<=EXO_REGNUM)
1426 supply_register(160 + (regno - FPE_REGNUM),(char *) &val);
1427 return; /* Pretend Success */
1431 From.Space = UDI29KSpecialRegs;
1432 From.Offset = regnum_to_srnum(regno);
1435 if (err = UDIRead(From, &To, Count, Size, &CountDone, HostEndian))
1436 error("UDIRead() failed in udi_fetch_registers");
1438 supply_register(regno, (char *) &To);
1441 printf_unfiltered("Fetching register %s = 0x%x\n", reg_names[regno], To);
1443 /*****************************************************************************/
1444 /* Store a single register indicated by 'regno'.
1445 * Returns 0/-1 on success/failure.
1448 store_register (regno)
1457 UDIBool HostEndian = 0;
1459 From = read_register (regno); /* get data value */
1462 printf_unfiltered("Storing register %s = 0x%x\n", reg_names[regno], From);
1464 if (regno == GR1_REGNUM)
1466 To.Space = UDI29KGlobalRegs;
1468 result = UDIWrite(&From, To, Count, Size, &CountDone, HostEndian);
1469 /* Setting GR1 changes the numbers of all the locals, so invalidate the
1470 * register cache. Do this *after* calling read_register, because we want
1471 * read_register to return the value that write_register has just stuffed
1472 * into the registers array, not the value of the register fetched from
1475 registers_changed ();
1477 #if defined(GR64_REGNUM)
1478 else if (regno >= GR64_REGNUM && regno < GR64_REGNUM + 32 )
1480 To.Space = UDI29KGlobalRegs;
1481 To.Offset = (regno - GR64_REGNUM) + 64;
1482 result = UDIWrite(&From, To, Count, Size, &CountDone, HostEndian);
1484 #endif /* GR64_REGNUM */
1485 else if (regno >= GR96_REGNUM && regno < GR96_REGNUM + 32)
1487 To.Space = UDI29KGlobalRegs;
1488 To.Offset = (regno - GR96_REGNUM) + 96;
1489 result = UDIWrite(&From, To, Count, Size, &CountDone, HostEndian);
1491 else if (regno >= LR0_REGNUM && regno < LR0_REGNUM + 128)
1493 To.Space = UDI29KLocalRegs;
1494 To.Offset = (regno - LR0_REGNUM);
1495 result = UDIWrite(&From, To, Count, Size, &CountDone, HostEndian);
1497 else if (regno >= FPE_REGNUM && regno <= EXO_REGNUM)
1498 return 0; /* Pretend Success */
1499 else if (regno == PC_REGNUM)
1501 /* PC1 via UDI29KPC */
1503 To.Space = UDI29KPC;
1504 To.Offset = 0; /* PC1 */
1505 result = UDIWrite (&From, To, Count, Size, &CountDone, HostEndian);
1507 /* Writing to this loc actually changes the values of pc0 & pc1 */
1509 register_valid[PC_REGNUM] = 0; /* pc1 */
1510 register_valid[NPC_REGNUM] = 0; /* pc0 */
1512 else /* An unprotected or protected special register */
1514 To.Space = UDI29KSpecialRegs;
1515 To.Offset = regnum_to_srnum(regno);
1516 result = UDIWrite(&From, To, Count, Size, &CountDone, HostEndian);
1520 error("UDIWrite() failed in store_registers");
1524 /********************************************************** REGNUM_TO_SRNUM */
1526 * Convert a gdb special register number to a 29000 special register number.
1529 regnum_to_srnum(regno)
1533 case VAB_REGNUM: return(0);
1534 case OPS_REGNUM: return(1);
1535 case CPS_REGNUM: return(2);
1536 case CFG_REGNUM: return(3);
1537 case CHA_REGNUM: return(4);
1538 case CHD_REGNUM: return(5);
1539 case CHC_REGNUM: return(6);
1540 case RBP_REGNUM: return(7);
1541 case TMC_REGNUM: return(8);
1542 case TMR_REGNUM: return(9);
1543 case NPC_REGNUM: return(USE_SHADOW_PC ? (20) : (10));
1544 case PC_REGNUM: return(USE_SHADOW_PC ? (21) : (11));
1545 case PC2_REGNUM: return(USE_SHADOW_PC ? (22) : (12));
1546 case MMU_REGNUM: return(13);
1547 case LRU_REGNUM: return(14);
1548 case IPC_REGNUM: return(128);
1549 case IPA_REGNUM: return(129);
1550 case IPB_REGNUM: return(130);
1551 case Q_REGNUM: return(131);
1552 case ALU_REGNUM: return(132);
1553 case BP_REGNUM: return(133);
1554 case FC_REGNUM: return(134);
1555 case CR_REGNUM: return(135);
1556 case FPE_REGNUM: return(160);
1557 case INTE_REGNUM: return(161);
1558 case FPS_REGNUM: return(162);
1559 case EXO_REGNUM:return(164);
1561 return(255); /* Failure ? */
1564 /****************************************************************************/
1566 * Determine the Target memory space qualifier based on the addr.
1567 * FIXME: Can't distinguis I_ROM/D_ROM.
1568 * FIXME: Doesn't know anything about I_CACHE/D_CACHE.
1571 udi_memory_space(addr)
1574 UDIUInt32 tstart = IMemStart;
1575 UDIUInt32 tend = tstart + IMemSize;
1576 UDIUInt32 dstart = DMemStart;
1577 UDIUInt32 dend = tstart + DMemSize;
1578 UDIUInt32 rstart = RMemStart;
1579 UDIUInt32 rend = tstart + RMemSize;
1581 if (((UDIUInt32)addr >= tstart) && ((UDIUInt32)addr < tend)) {
1582 return UDI29KIRAMSpace;
1583 } else if (((UDIUInt32)addr >= dstart) && ((UDIUInt32)addr < dend)) {
1584 return UDI29KDRAMSpace;
1585 } else if (((UDIUInt32)addr >= rstart) && ((UDIUInt32)addr < rend)) {
1586 /* FIXME: how do we determine between D_ROM and I_ROM */
1587 return UDI29KIROMSpace;
1588 } else /* FIXME: what do me do now? */
1589 return UDI29KDRAMSpace; /* Hmmm! */
1591 /*********************************************************************** STUBS
1594 void convert16() {;}
1595 void convert32() {;}
1596 GDB_FILE * EchoFile = 0; /* used for debugging */
1597 int QuietMode = 0; /* used for debugging */
1599 #ifdef NO_HIF_SUPPORT
1603 return(0); /* Emulate a failure */
1607 /* Target_ops vector. Not static because there does not seem to be
1608 any portable way to do a forward declaration of a static variable.
1609 The RS/6000 doesn't like "extern" followed by "static"; SunOS
1610 /bin/cc doesn't like "static" twice. */
1612 struct target_ops udi_ops = {
1614 "Remote UDI connected TIP",
1615 "Remote debug an AMD 29k using UDI socket connection to TIP process.\n\
1617 `configuration-id AF_INET hostname port-number'\n\
1618 To connect via the network, where hostname and port-number specify the\n\
1619 host and port where you can connect via UDI.\n\
1620 configuration-id is unused.\n\
1622 `configuration-id AF_UNIX socket-name tip-program'\n\
1623 To connect using a local connection to the \"tip.exe\" program which is\n\
1624 supplied by AMD. If socket-name specifies an AF_UNIX socket then the\n\
1625 tip program must already be started; connect to it using that socket.\n\
1626 If not, start up tip-program, which should be the name of the tip\n\
1627 program. If appropriate, the PATH environment variable is searched.\n\
1628 configuration-id is unused.\n\
1630 `configuration-id'\n\
1631 Look up the configuration in ./udi_soc or /etc/udi_soc, which\n\
1632 are files containing lines in the above formats. configuration-id is\n\
1633 used to pick which line of the file to use.",
1640 udi_fetch_registers,
1641 udi_store_registers,
1642 udi_prepare_to_store,
1643 udi_xfer_inferior_memory,
1645 udi_insert_breakpoint,
1646 udi_remove_breakpoint,
1647 0, /* termial_init */
1648 0, /* terminal_inferior */
1649 0, /* terminal_ours_for_output */
1650 0, /* terminal_ours */
1651 0, /* terminal_info */
1652 udi_kill, /* FIXME, kill */
1654 0, /* lookup_symbol */
1655 udi_create_inferior,
1656 udi_mourn, /* mourn_inferior FIXME */
1658 0, /* notice_signals */
1661 1, /* has_all_memory */
1664 1, /* has_registers */
1665 1, /* has_execution */
1667 0, /* sections_end */
1668 OPS_MAGIC, /* Always the last thing */
1672 _initialize_remote_udi ()
1674 add_target (&udi_ops);