]> Git Repo - binutils.git/blob - gdb/remote-udi.c
Added support for nev-v810 processor. A newlib *only* target, for now at
[binutils.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 ([email protected]) 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.
31  - Daniel Mann at AMD took the 3.95 adaptions above and replaced
32         MiniMON interface with UDI-p interface.   */
33  
34 #include "defs.h"
35 #include "inferior.h"
36 #include "wait.h"
37 #include "value.h"
38 #include <ctype.h>
39 #include <fcntl.h>
40 #include <signal.h>
41 #include <errno.h>
42 #include <string.h>
43 #include "terminal.h"
44 #include "target.h"
45 #include "29k-share/udi/udiproc.h"
46 #include "gdbcmd.h"
47 #include "bfd.h"
48 #include "gdbcore.h" /* For download function */
49
50 /* access the register store directly, without going through
51    the normal handler functions. This avoids an extra data copy.  */
52
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,
65                                               int len));
66 static int udi_read_inferior_memory PARAMS ((CORE_ADDR memaddr, char *myaddr,
67                                              int len));
68 static void download PARAMS ((char *load_arg_string, int from_tty));
69 char   CoffFileName[100] = "";
70
71 #define FREEZE_MODE     (read_register(CPS_REGNUM) & 0x400)
72 #define USE_SHADOW_PC   ((processor_type == a29k_freeze_mode) && FREEZE_MODE)
73
74 static int timeout = 5;
75 extern struct target_ops udi_ops;             /* Forward declaration */
76
77 /* Special register enumeration.
78 */
79
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
84    starts.  */
85
86 UDISessionId udi_session_id = -1;
87 static char *udi_config_id;
88
89 CPUOffset IMemStart = 0;
90 CPUSizeT IMemSize = 0;
91 CPUOffset DMemStart = 0;
92 CPUSizeT DMemSize = 0;
93 CPUOffset RMemStart = 0;
94 CPUSizeT RMemSize = 0;
95 UDIUInt32 CPUPRL;
96 UDIUInt32 CoProcPRL;
97
98 UDIMemoryRange address_ranges[2]; /* Text and data */
99 UDIResource entry = {0, 0};     /* Entry point */
100 CPUSizeT stack_sizes[2];        /* Regular and memory stacks */
101
102 #define SBUF_MAX        1024    /* maximum size of string handling buffer */
103 char sbuf[SBUF_MAX];
104
105 typedef struct  bkpt_entry_str
106 {
107     UDIResource  Addr;
108     UDIUInt32    PassCount;
109     UDIBreakType Type;
110     unsigned int BreakId;
111 } bkpt_entry_t;
112 #define         BKPT_TABLE_SIZE 40
113 static bkpt_entry_t     bkpt_table[BKPT_TABLE_SIZE];
114 extern  char    dfe_errmsg[];           /* error string */
115
116 /* malloc'd name of the program on the remote system.  */
117 static char *prog_name = NULL;
118
119 /* This is called not only when we first attach, but also when the
120    user types "run" after having attached.  */
121
122 static void
123 udi_create_inferior (execfile, args, env)
124      char *execfile;
125      char *args;
126      char **env;
127 {
128   char *args1;
129
130   if (execfile)
131     {
132       if (prog_name != NULL)
133         free (prog_name);
134       prog_name = savestring (execfile, strlen (execfile));
135     }
136   else if (entry.Offset)
137     execfile = "";
138   else
139     error ("No image loaded into target.");
140
141   if (udi_session_id < 0)
142     {
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.  */
147       entry.Offset = 0;
148     }
149
150   inferior_pid = 40000;
151
152   if (!entry.Offset)
153     download(execfile, 0);
154
155   args1 = alloca (strlen(execfile) + strlen(args) + 2);
156
157   if (execfile[0] == '\0')
158
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).  */
166
167     strcpy (args1, "''");
168   else
169     strcpy (args1, execfile);
170   strcat (args1, " ");
171   strcat (args1, args);
172
173   UDIInitializeProcess (address_ranges,         /* ProcessMemory[] */
174                         (UDIInt)2,              /* NumberOfRanges */
175                         entry,                  /* EntryPoint */
176                         stack_sizes,            /* *StackSizes */
177                         (UDIInt)2,              /* NumberOfStacks */
178                         args1);                 /* ArgString */
179
180   init_wait_for_inferior ();
181   clear_proceed_status ();
182   proceed (-1, TARGET_SIGNAL_DEFAULT, 0);
183 }
184
185 static void
186 udi_mourn()
187 {
188 #if 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 */
194 #endif
195   /* But if we're going to want to run it again, we better remove the
196      breakpoints...  */
197   remove_breakpoints ();
198   generic_mourn_inferior ();
199 }
200
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.
206  */
207
208 /* XXX - need cleanups for udiconnect for various failures!!! */
209
210 static void
211 udi_open (name, from_tty)
212      char *name;
213      int from_tty;
214 {
215   unsigned int prl;
216   char *p;
217   int cnt;
218   UDIMemoryRange KnownMemory[10];
219   UDIUInt32 ChipVersions[10];
220   UDIInt NumberOfRanges = 10;
221   UDIInt NumberOfChips = 10;
222   UDIPId PId;
223   UDIUInt32 TIPId, TargetId, DFEId, DFE, TIP, DFEIPCId, TIPIPCId;
224
225   target_preopen(from_tty);
226
227   entry.Offset = 0;
228
229   for (cnt = 0; cnt < BKPT_TABLE_SIZE; cnt++)
230     bkpt_table[cnt].Type = 0;
231
232   if (udi_config_id)
233     free (udi_config_id);
234
235   if (!name)
236     error("Usage: target udi config_id, where config_id appears in udi_soc file");
237
238   udi_config_id = strdup (strtok (name, " \t"));
239
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);
243
244   push_target (&udi_ops);
245
246   /*
247   ** Initialize target configuration structure (global)
248   */
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++)
255     {
256       switch(KnownMemory[cnt].Space)
257         {
258         default:
259           fprintf_unfiltered(gdb_stderr, "UDIGetTargetConfig() unknown memory space\n");
260           break;
261         case UDI29KCP_S:
262           break;
263         case UDI29KIROMSpace:
264           RMemStart = KnownMemory[cnt].Offset;
265           RMemSize = KnownMemory[cnt].Size;
266           break;
267         case UDI29KIRAMSpace:
268           IMemStart = KnownMemory[cnt].Offset;
269           IMemSize = KnownMemory[cnt].Size;
270           break;
271         case UDI29KDRAMSpace:
272           DMemStart = KnownMemory[cnt].Offset;
273           DMemSize = KnownMemory[cnt].Size;
274           break;
275         }
276     }
277
278   a29k_get_processor_type ();
279
280   if (UDICreateProcess (&PId))
281      fprintf_unfiltered(gdb_stderr, "UDICreateProcess() failed\n");
282
283   /* Print out some stuff, letting the user now what's going on */
284   if (UDICapabilities (&TIPId, &TargetId, DFEId, DFE, &TIP, &DFEIPCId,
285                        &TIPIPCId, sbuf))
286     error ("UDICapabilities() failed");
287   if (from_tty)
288     {
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,
294                        sbuf);
295     }
296 }
297
298 /******************************************************************* UDI_CLOSE
299    Close the open connection to the TIP process.
300    Use this when you want to detach and do something else
301    with your gdb.  */
302 static void
303 udi_close (quitting)    /*FIXME: how is quitting used */
304      int quitting;
305 {
306   if (udi_session_id < 0)
307     return;
308
309   /* We should never get here if there isn't something valid in
310      udi_session_id.  */
311
312   if (UDIDisconnect (udi_session_id, UDITerminateSession))
313     {
314       if (quitting)
315         warning ("UDIDisconnect() failed in udi_close");
316       else
317         error ("UDIDisconnect() failed in udi_close");
318     }
319
320   /* Do not try to close udi_session_id again, later in the program.  */
321   udi_session_id = -1;
322   inferior_pid = 0;
323
324   printf_filtered ("  Ending remote debugging\n");
325
326
327 /**************************************************************** UDI_ATACH */
328 /* Attach to a program that is already loaded and running 
329  * Upon exiting the process's execution is stopped.
330  */
331 static void
332 udi_attach (args, from_tty)
333      char *args;
334      int from_tty;
335 {
336   UDIResource   From;
337   UDIInt32      PC_adds;
338   UDICount      Count = 1;
339   UDISizeT      Size = 4;
340   UDICount      CountDone;
341   UDIBool       HostEndian = 0;
342   UDIError      err;
343
344   if (args == NULL)
345     error_no_arg ("program to attach");
346
347   if (udi_session_id < 0)
348       error ("UDI connection not opened yet, use the 'target udi' command.\n");
349         
350   if (from_tty)
351       printf_unfiltered ("Attaching to remote program %s...\n", prog_name);
352
353   UDIStop();
354   From.Space = UDI29KSpecialRegs;
355   From.Offset = 11;
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);
359 }
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). */
364 static void
365 udi_detach (args,from_tty)
366      char *args;
367      int from_tty;
368 {
369
370   remove_breakpoints();         /* Just in case there were any left in */
371
372   if (UDIDisconnect (udi_session_id, UDIContinueSession))
373     error ("UDIDisconnect() failed in udi_detach");
374
375   /* Don't try to UDIDisconnect it again in udi_close, which is called from
376      pop_target.  */
377   udi_session_id = -1;
378   inferior_pid = 0;
379
380   pop_target();
381
382   if (from_tty)
383     printf_unfiltered ("Detaching from TIP\n");
384 }
385
386
387 /****************************************************************** UDI_RESUME
388 ** Tell the remote machine to resume.  */
389
390 static void
391 udi_resume (pid, step, sig)
392      int pid, step;
393      enum target_signal sig;
394 {
395   UDIError tip_error;
396   UDIUInt32 Steps = 1;
397   UDIStepType StepType = UDIStepNatural;
398   UDIRange Range;
399
400   if (step)                     /* step 1 instruction */
401     {
402       tip_error = UDIStep (Steps, StepType, Range);
403       if (!tip_error)
404         return;
405
406       fprintf_unfiltered (gdb_stderr,  "UDIStep() error = %d\n", tip_error);
407       error ("failed in udi_resume");
408     }
409
410   if (UDIExecute())
411     error ("UDIExecute() failed in udi_resume");
412 }
413
414 /******************************************************************** UDI_WAIT
415 ** Wait until the remote machine stops, then return,
416    storing status in STATUS just as `wait' would.  */
417
418 static int
419 udi_wait (pid, status)
420      int pid;
421      struct target_waitstatus *status;
422 {
423   UDIInt32      MaxTime;
424   UDIPId        PId;
425   UDIInt32      StopReason;
426   UDISizeT      CountDone;
427   int           old_timeout = timeout;
428   int           old_immediate_quit = immediate_quit;
429   int           i;
430
431   status->kind = TARGET_WAITKIND_EXITED;
432   status->value.integer = 0;
433
434 /* wait for message to arrive. It should be:
435   If the target stops executing, udi_wait() should return.
436 */
437   timeout = 0;                  /* Wait indefinetly for a message */
438   immediate_quit = 1;           /* Helps ability to QUIT */
439
440   while(1)
441     {
442       i = 0;
443       MaxTime = UDIWaitForever;
444       UDIWait(MaxTime, &PId, &StopReason);
445       QUIT;                     /* Let user quit if they want */
446
447       switch (StopReason & UDIGrossState)
448         {
449         case UDIStdoutReady:
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);
457           continue;
458
459         case UDIStderrReady:
460           UDIGetStderr (sbuf, (UDISizeT)SBUF_MAX, &CountDone);
461           fwrite (sbuf, 1, CountDone, gdb_stderr);
462           gdb_flush(gdb_stderr);
463           continue;
464
465         case UDIStdinNeeded:
466           {
467             int ch;
468             i = 0;
469             do
470               {
471                 ch = getchar ();
472                 if (ch == EOF)
473                   break;
474                 sbuf[i++] = ch;
475               } while (i < SBUF_MAX && ch != '\n');
476             UDIPutStdin (sbuf, (UDISizeT)i, &CountDone);
477             continue;
478           }
479
480         case UDIRunning:
481           /* In spite of the fact that we told UDIWait to wait forever, it will
482              return spuriously sometimes.  */
483         case UDIStdinModeX:
484           continue;
485         default:
486           break;
487         }
488       break;
489     }
490
491   switch (StopReason & UDIGrossState)
492     {
493     case UDITrapped:
494       printf_unfiltered("Am290*0 received vector number %d\n", StopReason >> 24);
495           
496       switch (StopReason >> 8)
497         {
498         case 0:                 /* Illegal opcode */
499           printf_unfiltered("   (break point)\n");
500           status->kind = TARGET_WAITKIND_STOPPED;
501           status->value.sig = TARGET_SIGNAL_TRAP;
502           break;
503         case 1:                 /* Unaligned Access */
504           status->kind = TARGET_WAITKIND_STOPPED;
505           status->value.sig = TARGET_SIGNAL_BUS;
506           break;
507         case 3:
508         case 4:
509           status->kind = TARGET_WAITKIND_STOPPED;
510           status->value.sig = TARGET_SIGNAL_FPE;
511           break;
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;
516           break;
517         case 6:
518         case 7:
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;
525           break;
526         case 12:
527         case 13:
528           status->kind = TARGET_WAITKIND_STOPPED;
529           status->value.sig = TARGET_SIGNAL_ILL;
530           break;
531         case 14:                /* Timer */
532           status->kind = TARGET_WAITKIND_STOPPED;
533           status->value.sig = TARGET_SIGNAL_ALRM;
534           break;
535         case 15:                /* Trace */
536           status->kind = TARGET_WAITKIND_STOPPED;
537           status->value.sig = TARGET_SIGNAL_TRAP;
538           break;
539         case 16:                /* INTR0 */
540         case 17:                /* INTR1 */
541         case 18:                /* INTR2 */
542         case 19:                /* INTR3/Internal */
543         case 20:                /* TRAP0 */
544         case 21:                /* TRAP1 */
545           status->kind = TARGET_WAITKIND_STOPPED;
546           status->value.sig = TARGET_SIGNAL_INT;
547           break;
548         case 22:                /* Floating-Point Exception */
549           status->kind = TARGET_WAITKIND_STOPPED;
550           /* Why not FPE?  */
551           status->value.sig = TARGET_SIGNAL_ILL;
552           break;
553         case 77:                /* assert 77 */
554           status->kind = TARGET_WAITKIND_STOPPED;
555           status->value.sig = TARGET_SIGNAL_TRAP;
556           break;
557         default:
558           status->kind = TARGET_WAITKIND_EXITED;
559           status->value.integer = 0;
560         }
561       break;
562     case UDINotExecuting:
563       status->kind = TARGET_WAITKIND_STOPPED;
564       status->value.sig = TARGET_SIGNAL_TERM;
565       break;
566     case UDIStopped:
567       status->kind = TARGET_WAITKIND_STOPPED;
568       status->value.sig = TARGET_SIGNAL_TSTP;
569       break;
570     case UDIWarned:
571       status->kind = TARGET_WAITKIND_STOPPED;
572       status->value.sig = TARGET_SIGNAL_URG;
573       break;
574     case UDIStepped:
575     case UDIBreak:
576       status->kind = TARGET_WAITKIND_STOPPED;
577       status->value.sig = TARGET_SIGNAL_TRAP;
578       break;
579     case UDIWaiting:
580       status->kind = TARGET_WAITKIND_STOPPED;
581       status->value.sig = TARGET_SIGNAL_STOP;
582       break;
583     case UDIHalted:
584       status->kind = TARGET_WAITKIND_STOPPED;
585       status->value.sig = TARGET_SIGNAL_KILL;
586       break;
587     case UDIExited:
588     default:
589       status->kind = TARGET_WAITKIND_EXITED;
590       status->value.integer = 0;
591     }
592
593   timeout = old_timeout;        /* Restore original timeout value */
594   immediate_quit = old_immediate_quit;
595   return inferior_pid;
596 }
597
598 #if 0
599 /* Handy for debugging */
600 udi_pc()
601 {
602   UDIResource   From;
603   UDIUInt32     *To;
604   UDICount      Count;
605   UDISizeT      Size = 4;
606   UDICount      CountDone;
607   UDIBool       HostEndian = 0;
608   UDIError      err;
609   int pc[2];
610   unsigned long myregs[256];
611   int i;
612
613   From.Space = UDI29KPC;
614   From.Offset = 0;
615   To = (UDIUInt32 *)pc;
616   Count = 2;
617
618   err = UDIRead(From, To, Count, Size, &CountDone, HostEndian);
619
620   printf_unfiltered ("err = %d, CountDone = %d, pc[0] = 0x%x, pc[1] = 0x%x\n",
621           err, CountDone, pc[0], pc[1]);
622
623   udi_fetch_registers(-1);
624
625   printf_unfiltered("other pc1 = 0x%x, pc0 = 0x%x\n", *(int *)&registers[4 * PC_REGNUM],
626           *(int *)&registers[4 * NPC_REGNUM]);
627
628   /* Now, read all the registers globally */
629
630   From.Space = UDI29KGlobalRegs;
631   From.Offset = 0;
632   err = UDIRead(From, myregs, 256, 4, &CountDone, HostEndian);
633
634   printf ("err = %d, CountDone = %d\n", err, CountDone);
635
636   printf("\n");
637
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]);
641   printf("\n");
642
643   return pc[0];
644 }
645 #endif
646
647 /********************************************************** UDI_FETCH_REGISTERS
648  * Read a remote register 'regno'. 
649  * If regno==-1 then read all the registers.
650  */
651 static void 
652 udi_fetch_registers (regno)
653 int     regno;
654 {
655   UDIResource   From;
656   UDIUInt32     *To;
657   UDICount      Count;
658   UDISizeT      Size = 4;
659   UDICount      CountDone;
660   UDIBool       HostEndian = 0;
661   UDIError      err;
662   int           i;
663
664   if (regno >= 0)  {
665     fetch_register(regno);
666     return;
667   }
668
669 /* Gr1/rsp */
670
671   From.Space = UDI29KGlobalRegs;
672   From.Offset = 1;
673   To = (UDIUInt32 *)&registers[4 * GR1_REGNUM];
674   Count = 1;
675   if (err = UDIRead(From, To, Count, Size, &CountDone, HostEndian))
676     error("UDIRead() failed in udi_fetch_registers");
677
678   register_valid[GR1_REGNUM] = 1;
679
680 #if defined(GR64_REGNUM)        /* Read gr64-127 */
681
682 /* Global Registers gr64-gr95 */ 
683
684   From.Space = UDI29KGlobalRegs;
685   From.Offset = 64;
686   To = (UDIUInt32 *)&registers[4 * GR64_REGNUM];
687   Count = 32;
688   if (err = UDIRead(From, To, Count, Size, &CountDone, HostEndian))
689     error("UDIRead() failed in udi_fetch_registers");
690
691   for (i = GR64_REGNUM; i < GR64_REGNUM + 32; i++)
692     register_valid[i] = 1;
693
694 #endif  /*  GR64_REGNUM */
695
696 /* Global Registers gr96-gr127 */ 
697
698   From.Space = UDI29KGlobalRegs;
699   From.Offset = 96;
700   To = (UDIUInt32 *)&registers[4 * GR96_REGNUM];
701   Count = 32;
702   if (err = UDIRead(From, To, Count, Size, &CountDone, HostEndian))
703     error("UDIRead() failed in udi_fetch_registers");
704
705   for (i = GR96_REGNUM; i < GR96_REGNUM + 32; i++)
706     register_valid[i] = 1;
707
708 /* Local Registers */
709
710   From.Space = UDI29KLocalRegs;
711   From.Offset = 0;
712   To = (UDIUInt32 *)&registers[4 * LR0_REGNUM];
713   Count = 128;
714   if (err = UDIRead(From, To, Count, Size, &CountDone, HostEndian))
715     error("UDIRead() failed in udi_fetch_registers");
716
717   for (i = LR0_REGNUM; i < LR0_REGNUM + 128; i++)
718     register_valid[i] = 1;
719
720 /* Protected Special Registers */
721
722   From.Space = UDI29KSpecialRegs;
723   From.Offset = 0;
724   To = (UDIUInt32 *)&registers[4 * SR_REGNUM(0)];
725   Count = 15;
726   if (err = UDIRead(From, To, Count, Size, &CountDone, HostEndian))
727     error("UDIRead() failed in udi_fetch_registers");
728
729   for (i = SR_REGNUM(0); i < SR_REGNUM(0) + 15; i++)
730     register_valid[i] = 1;
731
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);
736
737 /* Unprotected Special Registers sr128-sr135 */
738
739     From.Space = UDI29KSpecialRegs;
740     From.Offset = 128;
741     To = (UDIUInt32 *)&registers[4 * SR_REGNUM(128)];
742     Count = 135-128 + 1;
743     if (err = UDIRead(From, To, Count, Size, &CountDone, HostEndian))
744       error("UDIRead() failed in udi_fetch_registers");
745
746     for (i = SR_REGNUM(128); i < SR_REGNUM(128) + 135-128+1; i++)
747       register_valid[i] = 1;
748   }
749
750   if (remote_debug)
751     {
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));
756     }
757
758   /* There doesn't seem to be any way to get these.  */
759   {
760     int val = -1;
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);
765   }
766 }
767
768
769 /********************************************************* UDI_STORE_REGISTERS
770 ** Store register regno into the target.  
771  * If regno==-1 then store all the registers.
772  */
773
774 static void
775 udi_store_registers (regno)
776 int regno;
777 {
778   UDIUInt32     *From;
779   UDIResource   To;
780   UDICount      Count;
781   UDISizeT      Size = 4;
782   UDICount      CountDone;
783   UDIBool       HostEndian = 0;
784   
785   if (regno >= 0)
786     {
787       store_register(regno);
788       return;
789     }
790
791   if (remote_debug)
792     {
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));
796     }
797
798 /* Gr1/rsp */
799
800   From = (UDIUInt32 *)&registers[4 * GR1_REGNUM];
801   To.Space = UDI29KGlobalRegs;
802   To.Offset = 1;
803   Count = 1;
804   if(UDIWrite(From, To, Count, Size, &CountDone, HostEndian))
805     error("UDIWrite() failed in udi_store_regisetrs");
806
807 #if defined(GR64_REGNUM)
808
809 /* Global registers gr64-gr95 */
810
811   From = (UDIUInt32 *)&registers[4 * GR64_REGNUM];
812   To.Space = UDI29KGlobalRegs;
813   To.Offset = 64;
814   Count = 32;
815   if(UDIWrite(From, To, Count, Size, &CountDone, HostEndian))
816     error("UDIWrite() failed in udi_store_regisetrs");
817
818 #endif  /* GR64_REGNUM */
819
820 /* Global registers gr96-gr127 */
821
822   From = (UDIUInt32 *)&registers[4 * GR96_REGNUM];
823   To.Space = UDI29KGlobalRegs;
824   To.Offset = 96;
825   Count = 32;
826   if(UDIWrite(From, To, Count, Size, &CountDone, HostEndian))
827     error("UDIWrite() failed in udi_store_regisetrs");
828
829 /* Local Registers */
830
831   From = (UDIUInt32 *)&registers[4 * LR0_REGNUM];
832   To.Space = UDI29KLocalRegs;
833   To.Offset = 0;
834   Count = 128;
835   if(UDIWrite(From, To, Count, Size, &CountDone, HostEndian))
836     error("UDIWrite() failed in udi_store_regisetrs");
837
838
839 /* Protected Special Registers */ /* VAB through TMR */
840
841   From = (UDIUInt32 *)&registers[4 * SR_REGNUM(0)];
842   To.Space = UDI29KSpecialRegs;
843   To.Offset = 0;
844   Count = 10;
845   if(UDIWrite(From, To, Count, Size, &CountDone, HostEndian))
846     error("UDIWrite() failed in udi_store_regisetrs");
847
848 /* PC0, PC1, PC2 possibly as shadow registers */
849
850   From = (UDIUInt32 *)&registers[4 * SR_REGNUM(10)];
851   To.Space = UDI29KSpecialRegs;
852   Count = 3;
853   if (USE_SHADOW_PC) 
854     To.Offset = 20;                             /* SPC0 */
855   else 
856     To.Offset = 10;                             /* PC0 */
857   if(UDIWrite(From, To, Count, Size, &CountDone, HostEndian))
858     error("UDIWrite() failed in udi_store_regisetrs");
859
860 /* PC1 via UDI29KPC */
861
862   From = (UDIUInt32 *)&registers[4 * PC_REGNUM];
863   To.Space = UDI29KPC;
864   To.Offset = 0;                                /* PC1 */
865   Count = 1;
866   if (UDIWrite (From, To, Count, Size, &CountDone, HostEndian))
867     error ("UDIWrite() failed in udi_store_regisetrs");
868
869   /* LRU and MMU */
870
871   From = (UDIUInt32 *)&registers[4 * SR_REGNUM(13)];
872   To.Space = UDI29KSpecialRegs;
873   To.Offset = 13;
874   Count = 2;
875   if(UDIWrite(From, To, Count, Size, &CountDone, HostEndian))
876     error("UDIWrite() failed in udi_store_regisetrs");
877
878 /* Unprotected Special Registers */ 
879
880   From = (UDIUInt32 *)&registers[4 * SR_REGNUM(128)];
881   To.Space = UDI29KSpecialRegs;
882   To.Offset = 128;
883   Count = 135-128 +1;
884   if(UDIWrite(From, To, Count, Size, &CountDone, HostEndian))
885     error("UDIWrite() failed in udi_store_regisetrs");
886
887   registers_changed ();
888 }
889
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
895    debugged.  */
896
897 static void
898 udi_prepare_to_store ()
899 {
900   /* Do nothing, since we can store individual regs */
901 }
902
903 /********************************************************** TRANSLATE_ADDR */
904 static CORE_ADDR
905 translate_addr(addr)
906 CORE_ADDR addr;
907 {
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);
916         } else {
917                 return(addr);
918         }
919 #else
920         return(addr);
921 #endif
922 }
923 /************************************************* UDI_XFER_INFERIOR_MEMORY */
924 /* FIXME!  Merge these two.  */
925 static int
926 udi_xfer_inferior_memory (memaddr, myaddr, len, write)
927      CORE_ADDR memaddr;
928      char *myaddr;
929      int len;
930      int write;
931 {
932
933   memaddr = translate_addr(memaddr);
934
935   if (write)
936     return udi_write_inferior_memory (memaddr, myaddr, len);
937   else
938     return udi_read_inferior_memory (memaddr, myaddr, len);
939 }
940
941 /********************************************************** UDI_FILES_INFO */
942 static void
943 udi_files_info ()
944 {
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");
949 }
950
951 /**************************************************** UDI_INSERT_BREAKPOINT */
952 static int
953 udi_insert_breakpoint (addr, contents_cache)
954      CORE_ADDR addr;
955      char *contents_cache;
956 {
957   int cnt;
958   UDIError err;
959
960   for (cnt = 0; cnt < BKPT_TABLE_SIZE; cnt++)
961     if (bkpt_table[cnt].Type == 0) /* Find first free slot */
962       break;
963
964   if(cnt >= BKPT_TABLE_SIZE)
965     error("Too many breakpoints set");
966
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;
971   
972   err = UDISetBreakpoint(bkpt_table[cnt].Addr,
973                          bkpt_table[cnt].PassCount,
974                          bkpt_table[cnt].Type,
975                          &bkpt_table[cnt].BreakId);
976
977   if (err == 0) return 0;               /* Success */
978
979   bkpt_table[cnt].Type = 0;
980   error("UDISetBreakpoint returned error code %d\n", err);
981 }
982
983 /**************************************************** UDI_REMOVE_BREAKPOINT */
984 static int
985 udi_remove_breakpoint (addr, contents_cache)
986      CORE_ADDR addr;
987      char *contents_cache;
988 {
989   int cnt;
990   UDIError err;
991
992   for (cnt = 0; cnt < BKPT_TABLE_SIZE; cnt++)
993     if (bkpt_table[cnt].Addr.Offset == addr) /* Find matching breakpoint */
994       break;
995
996   if(cnt >= BKPT_TABLE_SIZE)
997     error("Can't find breakpoint in table");
998
999   bkpt_table[cnt].Type = 0;
1000
1001   err = UDIClearBreakpoint(bkpt_table[cnt].BreakId);
1002   if (err == 0) return 0;       /* Success */
1003
1004   error("UDIClearBreakpoint returned error code %d\n", err);
1005 }
1006
1007 static void
1008 udi_kill(arg,from_tty)
1009      char *arg;
1010      int from_tty;
1011 {
1012
1013 #if 0
1014 /*
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.
1018 */
1019   UDIStop();
1020
1021   udi_session_id = -1;
1022   inferior_pid = 0;
1023
1024   if (from_tty)
1025     printf_unfiltered("Target has been stopped.");
1026 #endif /* 0 */
1027 #if 0
1028   udi_close(0);
1029   pop_target();
1030 #endif /* 0 */
1031
1032   /* Keep the target around, e.g. so "run" can do the right thing when
1033      we are already debugging something.  */
1034
1035   if (UDIDisconnect (udi_session_id, UDITerminateSession))
1036     {
1037       warning ("UDIDisconnect() failed");
1038     }
1039
1040   /* Do not try to close udi_session_id again, later in the program.  */
1041   udi_session_id = -1;
1042   inferior_pid = 0;
1043 }
1044
1045 /* 
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.)
1049
1050    The options are:
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
1059   */
1060
1061 static void
1062 download(load_arg_string, from_tty)
1063      char *load_arg_string;
1064      int from_tty;
1065 {
1066 #define DEFAULT_MEM_STACK_SIZE          0x6000
1067 #define DEFAULT_REG_STACK_SIZE          0x2000
1068
1069   char *token;
1070   char *filename;
1071   asection *section;
1072   bfd *pbfd;
1073   UDIError err;
1074   int load_text = 1, load_data = 1, load_bss = 1, load_lit = 1;
1075
1076   address_ranges[0].Space = UDI29KIRAMSpace;
1077   address_ranges[0].Offset = 0xffffffff;
1078   address_ranges[0].Size = 0;
1079
1080   address_ranges[1].Space = UDI29KDRAMSpace;
1081   address_ranges[1].Offset = 0xffffffff;
1082   address_ranges[1].Size = 0;
1083
1084   stack_sizes[0] = DEFAULT_REG_STACK_SIZE;
1085   stack_sizes[1] = DEFAULT_MEM_STACK_SIZE;
1086
1087   dont_repeat ();
1088
1089   filename = strtok(load_arg_string, " \t");
1090   if (!filename)
1091     error ("Must specify at least a file name with the load command");
1092
1093   filename = tilde_expand (filename);
1094   make_cleanup (free, filename);
1095
1096   while (token = strtok (NULL, " \t"))
1097     {
1098       if (token[0] == '-')
1099         {
1100           token++;
1101
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"));
1106           else
1107             {
1108               load_text = load_data = load_bss = load_lit = 0;
1109
1110               while (*token)
1111                 {
1112                   switch (*token++)
1113                     {
1114                     case 't':
1115                     case 'T':
1116                       load_text = 1;
1117                       break;
1118                     case 'd':
1119                     case 'D':
1120                       load_data = 1;
1121                       break;
1122                     case 'b':
1123                     case 'B':
1124                       load_bss = 1;
1125                       break;
1126                     case 'l':
1127                     case 'L':
1128                       load_lit = 1;
1129                       break;
1130                     default:
1131                       error ("Unknown UDI load option -%s", token-1);
1132                     }
1133                 }
1134             }
1135         }
1136     }
1137
1138   pbfd = bfd_openr (filename, gnutarget);
1139
1140   if (!pbfd) 
1141     perror_with_name (filename);
1142   
1143   make_cleanup (bfd_close, pbfd);
1144
1145   QUIT;
1146   immediate_quit++;
1147
1148   if (!bfd_check_format (pbfd, bfd_object)) 
1149     error ("It doesn't seem to be an object file");
1150   
1151   for (section = pbfd->sections; section; section = section->next) 
1152     {
1153       if (bfd_get_section_flags (pbfd, section) & SEC_ALLOC)
1154         {
1155           UDIResource To;
1156           UDICount Count;
1157           unsigned long section_size, section_end;
1158           const char *section_name;
1159
1160           section_name = bfd_get_section_name (pbfd, section);
1161           if (STREQ (section_name, ".text") && !load_text)
1162             continue;
1163           else if (STREQ (section_name, ".data") && !load_data)
1164             continue;
1165           else if (STREQ (section_name, ".bss") && !load_bss)
1166             continue;
1167           else if (STREQ (section_name, ".lit") && !load_lit)
1168             continue;
1169
1170           To.Offset = bfd_get_section_vma (pbfd, section);
1171           section_size = bfd_section_size (pbfd, section);
1172           section_end = To.Offset + section_size;
1173
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.  */
1177             continue;
1178
1179           printf_unfiltered("[Loading section %s at %x (%d bytes)]\n",
1180                  section_name,
1181                  To.Offset,
1182                  section_size);
1183
1184           if (bfd_get_section_flags (pbfd, section) & SEC_CODE)
1185             {
1186               To.Space = UDI29KIRAMSpace;
1187
1188               address_ranges[0].Offset = min (address_ranges[0].Offset,
1189                                               To.Offset);
1190               address_ranges[0].Size = max (address_ranges[0].Size,
1191                                             section_end
1192                                             - address_ranges[0].Offset);
1193             }
1194           else
1195             {
1196               To.Space = UDI29KDRAMSpace;
1197
1198               address_ranges[1].Offset = min (address_ranges[1].Offset,
1199                                               To.Offset);
1200               address_ranges[1].Size = max (address_ranges[1].Size,
1201                                             section_end
1202                                             - address_ranges[1].Offset);
1203             }
1204
1205           if (bfd_get_section_flags (pbfd, section) & SEC_LOAD) /* Text, data or lit */
1206             {
1207               file_ptr fptr;
1208
1209               fptr = 0;
1210
1211               while (section_size > 0)
1212                 {
1213                   char buffer[1024];
1214
1215                   Count = min (section_size, 1024);
1216
1217                   bfd_get_section_contents (pbfd, section, buffer, fptr,
1218                                             Count);
1219
1220                   err = UDIWrite ((UDIHostMemPtr)buffer, /* From */
1221                                   To,                   /* To */
1222                                   Count,                /* Count */
1223                                   (UDISizeT)1,          /* Size */
1224                                   &Count,               /* CountDone */
1225                                   (UDIBool)0);          /* HostEndian */
1226                   if (err)
1227                     error ("UDIWrite failed, error = %d", err);
1228
1229                   To.Offset += Count;
1230                   fptr += Count;
1231                   section_size -= Count;
1232                 }
1233             }
1234           else                  /* BSS */
1235             {
1236               UDIResource From;
1237               unsigned long zero = 0;
1238
1239               /* Write a zero byte at the vma */
1240               /* FIXME: Broken for sections of 1-3 bytes (we test for
1241                  zero above).  */
1242               err = UDIWrite ((UDIHostMemPtr)&zero,     /* From */
1243                               To,                       /* To */
1244                               (UDICount)1,              /* Count */
1245                               (UDISizeT)4,              /* Size */
1246                               &Count,                   /* CountDone */
1247                               (UDIBool)0);              /* HostEndian */
1248               if (err)
1249                 error ("UDIWrite failed, error = %d", err);
1250
1251               From = To;
1252               To.Offset+=4;
1253
1254               /* Now, duplicate it for the length of the BSS */
1255               err = UDICopy (From,                      /* From */
1256                              To,                        /* To */
1257                              (UDICount)(section_size/4 - 1), /* Count */
1258                              (UDISizeT)4,               /* Size */
1259                              &Count,                    /* CountDone */
1260                              (UDIBool)1);               /* Direction */
1261               if (err)
1262                 {
1263                   char message[100];
1264                   int xerr;
1265
1266                   xerr = UDIGetErrorMsg(err, 100, message, &Count);
1267                   if (!xerr)
1268                     fprintf_unfiltered (gdb_stderr, "Error is %s\n", message);
1269                   else
1270                     fprintf_unfiltered (gdb_stderr, "xerr is %d\n", xerr);
1271                   error ("UDICopy failed, error = %d", err);
1272                 }
1273             }
1274
1275         }
1276     }
1277
1278   entry.Space = UDI29KIRAMSpace;
1279   entry.Offset = bfd_get_start_address (pbfd);
1280   
1281   immediate_quit--;
1282 }
1283
1284 /* User interface to download an image into the remote target.  See download()
1285  * for details on args.
1286  */
1287
1288 static void
1289 udi_load(args, from_tty)
1290      char *args;
1291      int from_tty;
1292 {
1293   download (args, from_tty);
1294
1295   symbol_file_add (strtok (args, " \t"), from_tty, 0, 0, 0, 0);
1296 }
1297
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.  */
1301 static int
1302 udi_write_inferior_memory (memaddr, myaddr, len)
1303      CORE_ADDR memaddr;
1304      char *myaddr;
1305      int len;
1306 {
1307   int           nwritten = 0;
1308   UDIUInt32     *From;
1309   UDIResource   To;
1310   UDICount      Count;
1311   UDISizeT      Size = 1;
1312   UDICount      CountDone = 0;
1313   UDIBool       HostEndian = 0;
1314   
1315   To.Space = udi_memory_space(memaddr);
1316   From = (UDIUInt32*)myaddr;
1317
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");
1324            break;       
1325         }
1326         else
1327         {  nwritten += CountDone;
1328            From += CountDone;
1329         }
1330   }
1331   return(nwritten);
1332 }
1333
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.  */
1337 static int
1338 udi_read_inferior_memory(memaddr, myaddr, len)
1339      CORE_ADDR memaddr;
1340      char *myaddr;
1341      int len;
1342 {
1343   int           nread = 0;
1344   UDIResource   From;
1345   UDIUInt32     *To;
1346   UDICount      Count;
1347   UDISizeT      Size = 1;
1348   UDICount      CountDone = 0;
1349   UDIBool       HostEndian = 0;
1350   UDIError      err;
1351   
1352   From.Space = udi_memory_space(memaddr);       
1353   To = (UDIUInt32*)myaddr;
1354
1355   while (nread < len)
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");
1361            break;       
1362         }
1363         else
1364         {  nread += CountDone;
1365            To += CountDone;
1366         }
1367   }
1368   return(nread);
1369 }
1370
1371 /********************************************************************* WARNING
1372 */
1373 udi_warning(num)
1374 int     num;
1375 {
1376     error ("ERROR while loading program into remote TIP: $d\n", num);
1377 }
1378
1379
1380 /*****************************************************************************/ 
1381 /* Fetch a single register indicatated by 'regno'. 
1382  * Returns 0/-1 on success/failure.  
1383  */
1384 static void
1385 fetch_register (regno)
1386      int regno;
1387 {
1388   UDIResource   From;
1389   UDIUInt32     To;
1390   UDICount      Count = 1;
1391   UDISizeT      Size = 4;
1392   UDICount      CountDone;
1393   UDIBool       HostEndian = 0;
1394   UDIError      err;
1395   int           result;
1396
1397   if (regno == GR1_REGNUM)
1398     {
1399       From.Space = UDI29KGlobalRegs;
1400       From.Offset = 1;
1401     }
1402   else if (regno >= GR96_REGNUM && regno < GR96_REGNUM + 32)
1403     {
1404       From.Space = UDI29KGlobalRegs;
1405       From.Offset = (regno - GR96_REGNUM) + 96;;
1406     }
1407
1408 #if defined(GR64_REGNUM)
1409
1410   else if (regno >= GR64_REGNUM && regno < GR64_REGNUM + 32 )
1411     {
1412       From.Space = UDI29KGlobalRegs;
1413       From.Offset = (regno - GR64_REGNUM) + 64;
1414     }
1415
1416 #endif  /* GR64_REGNUM */
1417
1418   else if (regno >= LR0_REGNUM && regno < LR0_REGNUM + 128)
1419     {
1420       From.Space = UDI29KLocalRegs;
1421       From.Offset = (regno - LR0_REGNUM);
1422     }
1423   else if (regno>=FPE_REGNUM && regno<=EXO_REGNUM)  
1424     {
1425       int val = -1;
1426       supply_register(160 + (regno - FPE_REGNUM),(char *) &val);
1427       return;           /* Pretend Success */
1428     }
1429   else 
1430     {
1431       From.Space = UDI29KSpecialRegs;
1432       From.Offset = regnum_to_srnum(regno); 
1433     }
1434
1435   if (err = UDIRead(From, &To, Count, Size, &CountDone, HostEndian))
1436     error("UDIRead() failed in udi_fetch_registers");
1437
1438   supply_register(regno, (char *) &To);
1439
1440   if (remote_debug)
1441     printf_unfiltered("Fetching register %s = 0x%x\n", reg_names[regno], To);
1442 }
1443 /*****************************************************************************/ 
1444 /* Store a single register indicated by 'regno'. 
1445  * Returns 0/-1 on success/failure.  
1446  */
1447 static int
1448 store_register (regno)
1449      int regno;
1450 {
1451   int           result;
1452   UDIUInt32     From;
1453   UDIResource   To;
1454   UDICount      Count = 1;
1455   UDISizeT      Size = 4;
1456   UDICount      CountDone;
1457   UDIBool       HostEndian = 0;
1458
1459   From =  read_register (regno);        /* get data value */
1460
1461   if (remote_debug)
1462     printf_unfiltered("Storing register %s = 0x%x\n", reg_names[regno], From);
1463
1464   if (regno == GR1_REGNUM)
1465     {
1466       To.Space = UDI29KGlobalRegs;
1467       To.Offset = 1;
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 
1473        * the inferior.  
1474        */
1475       registers_changed ();
1476     }
1477 #if defined(GR64_REGNUM)
1478   else if (regno >= GR64_REGNUM && regno < GR64_REGNUM + 32 )
1479     {
1480       To.Space = UDI29KGlobalRegs;
1481       To.Offset = (regno - GR64_REGNUM) + 64;
1482       result = UDIWrite(&From, To, Count, Size, &CountDone, HostEndian);
1483     }
1484 #endif  /* GR64_REGNUM */
1485   else if (regno >= GR96_REGNUM && regno < GR96_REGNUM + 32)
1486     {
1487       To.Space = UDI29KGlobalRegs;
1488       To.Offset = (regno - GR96_REGNUM) + 96;
1489       result = UDIWrite(&From, To, Count, Size, &CountDone, HostEndian);
1490     }
1491   else if (regno >= LR0_REGNUM && regno < LR0_REGNUM + 128)
1492     {
1493       To.Space = UDI29KLocalRegs;
1494       To.Offset = (regno - LR0_REGNUM);
1495       result = UDIWrite(&From, To, Count, Size, &CountDone, HostEndian);
1496     }
1497   else if (regno >= FPE_REGNUM && regno <= EXO_REGNUM)  
1498     return 0;           /* Pretend Success */
1499   else if (regno == PC_REGNUM)
1500     {    
1501       /* PC1 via UDI29KPC */
1502
1503       To.Space = UDI29KPC;
1504       To.Offset = 0;            /* PC1 */
1505       result = UDIWrite (&From, To, Count, Size, &CountDone, HostEndian);
1506
1507       /* Writing to this loc actually changes the values of pc0 & pc1 */
1508
1509       register_valid[PC_REGNUM] = 0; /* pc1 */
1510       register_valid[NPC_REGNUM] = 0; /* pc0 */
1511     }
1512   else  /* An unprotected or protected special register */
1513     {
1514       To.Space = UDI29KSpecialRegs;
1515       To.Offset = regnum_to_srnum(regno); 
1516       result = UDIWrite(&From, To, Count, Size, &CountDone, HostEndian);
1517     }
1518
1519   if (result != 0)
1520     error("UDIWrite() failed in store_registers");
1521
1522   return 0;
1523 }
1524 /********************************************************** REGNUM_TO_SRNUM */
1525 /* 
1526  * Convert a gdb special register number to a 29000 special register number.
1527  */
1528 static int
1529 regnum_to_srnum(regno)
1530 int     regno;
1531 {
1532         switch(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); 
1560                 default:
1561                         return(255);    /* Failure ? */
1562         }
1563 }
1564 /****************************************************************************/
1565 /*
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.
1569  */
1570 static CPUSpace
1571 udi_memory_space(addr)
1572 CORE_ADDR       addr;
1573 {
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;  
1580
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! */
1590 }
1591 /*********************************************************************** STUBS
1592 */
1593
1594 void  convert16() {;}
1595 void  convert32() {;}
1596 GDB_FILE * EchoFile = 0;                /* used for debugging */
1597 int   QuietMode = 0;            /* used for debugging */
1598 \f
1599 #ifdef NO_HIF_SUPPORT
1600 service_HIF(msg)
1601      union msg_t *msg;
1602 {
1603   return(0);                    /* Emulate a failure */
1604 }
1605 #endif
1606 \f
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.  */
1611
1612 struct target_ops udi_ops = {
1613         "udi",
1614         "Remote UDI connected TIP",
1615         "Remote debug an AMD 29k using UDI socket connection to TIP process.\n\
1616 Arguments are\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\
1621 \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\
1629 \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.",
1634         udi_open,
1635         udi_close,
1636         udi_attach,
1637         udi_detach,
1638         udi_resume,
1639         udi_wait,
1640         udi_fetch_registers,
1641         udi_store_registers,
1642         udi_prepare_to_store,
1643         udi_xfer_inferior_memory,
1644         udi_files_info,
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 */
1653         udi_load,
1654         0,                      /* lookup_symbol */
1655         udi_create_inferior,
1656         udi_mourn,              /* mourn_inferior FIXME */
1657         0,                      /* can_run */
1658         0,                      /* notice_signals */
1659         process_stratum,
1660         0,                      /* next */
1661         1,                      /* has_all_memory */
1662         1,                      /* has_memory */
1663         1,                      /* has_stack */
1664         1,                      /* has_registers */
1665         1,                      /* has_execution */
1666         0,                      /* sections */
1667         0,                      /* sections_end */
1668         OPS_MAGIC,              /* Always the last thing */
1669 };
1670
1671 void
1672 _initialize_remote_udi ()
1673 {
1674   add_target (&udi_ops);
1675 }
This page took 0.119492 seconds and 4 git commands to generate.