Wed Aug 31 14:40:33 1994 Jason Molenda (crash@phydeaux.cygnus.com)
[platform/upstream/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 (wood@lab.ultra.nyu.edu) at New York University adapted this
29         file to gdb 3.95.  I was unable to get this working on sun3os4
30         with termio, only with sgtty.
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 "frame.h"
36 #include "inferior.h"
37 #include "wait.h"
38 #include "value.h"
39 #include <ctype.h>
40 #include <fcntl.h>
41 #include <signal.h>
42 #include <errno.h>
43 #include <string.h>
44 #include "terminal.h"
45 #include "target.h"
46 #include "29k-share/udi/udiproc.h"
47 #include "gdbcmd.h"
48 #include "bfd.h"
49 #include "gdbcore.h" /* For download function */
50
51 /* access the register store directly, without going through
52    the normal handler functions. This avoids an extra data copy.  */
53
54 extern int stop_soon_quietly;           /* for wait_for_inferior */
55 extern struct value *call_function_by_hand();
56 static void udi_resume PARAMS ((int pid, int step, enum target_signal sig));
57 static void udi_fetch_registers PARAMS ((int regno));
58 static void udi_load PARAMS ((char *args, int from_tty));
59 static void fetch_register PARAMS ((int regno));
60 static void udi_store_registers PARAMS ((int regno));
61 static int store_register PARAMS ((int regno));
62 static int regnum_to_srnum PARAMS ((int regno));
63 static void udi_close PARAMS ((int quitting));
64 static CPUSpace udi_memory_space PARAMS ((CORE_ADDR addr));
65 static int udi_write_inferior_memory PARAMS ((CORE_ADDR memaddr, char *myaddr,
66                                               int len));
67 static int udi_read_inferior_memory PARAMS ((CORE_ADDR memaddr, char *myaddr,
68                                              int len));
69 static void download PARAMS ((char *load_arg_string, int from_tty));
70 char   CoffFileName[100] = "";
71
72 #define FREEZE_MODE     (read_register(CPS_REGNUM) & 0x400)
73 #define USE_SHADOW_PC   ((processor_type == a29k_freeze_mode) && FREEZE_MODE)
74
75 static int timeout = 5;
76 extern struct target_ops udi_ops;             /* Forward declaration */
77
78 /* Special register enumeration.
79 */
80
81 /******************************************************************* UDI DATA*/
82 #define MAXDATA         2*1024          /* max UDI[read/write] byte size */
83 /* Descriptor for I/O to remote machine.  Initialize it to -1 so that
84    udi_open knows that we don't have a file open when the program
85    starts.  */
86
87 UDISessionId udi_session_id = -1;
88 static char *udi_config_id;
89
90 CPUOffset IMemStart = 0;
91 CPUSizeT IMemSize = 0;
92 CPUOffset DMemStart = 0;
93 CPUSizeT DMemSize = 0;
94 CPUOffset RMemStart = 0;
95 CPUSizeT RMemSize = 0;
96 UDIUInt32 CPUPRL;
97 UDIUInt32 CoProcPRL;
98
99 UDIMemoryRange address_ranges[2]; /* Text and data */
100 UDIResource entry = {0, 0};     /* Entry point */
101 CPUSizeT stack_sizes[2];        /* Regular and memory stacks */
102
103 #define SBUF_MAX        1024    /* maximum size of string handling buffer */
104 char sbuf[SBUF_MAX];
105
106 typedef struct  bkpt_entry_str
107 {
108     UDIResource  Addr;
109     UDIUInt32    PassCount;
110     UDIBreakType Type;
111     unsigned int BreakId;
112 } bkpt_entry_t;
113 #define         BKPT_TABLE_SIZE 40
114 static bkpt_entry_t     bkpt_table[BKPT_TABLE_SIZE];
115 extern  char    dfe_errmsg[];           /* error string */
116
117 /* malloc'd name of the program on the remote system.  */
118 static char *prog_name = NULL;
119
120 /* This is called not only when we first attach, but also when the
121    user types "run" after having attached.  */
122
123 static void
124 udi_create_inferior (execfile, args, env)
125      char *execfile;
126      char *args;
127      char **env;
128 {
129   char *args1;
130
131   if (execfile)
132     {
133       if (prog_name != NULL)
134         free (prog_name);
135       prog_name = savestring (execfile, strlen (execfile));
136     }
137   else if (entry.Offset)
138     execfile = "";
139   else
140     error ("No image loaded into target.");
141
142   if (udi_session_id < 0)
143     {
144       /* If the TIP is not open, open it.  */
145       if (UDIConnect (udi_config_id, &udi_session_id))
146         error("UDIConnect() failed: %s\n", dfe_errmsg);
147       /* We will need to download the program.  */
148       entry.Offset = 0;
149     }
150
151   inferior_pid = 40000;
152
153   if (!entry.Offset)
154     download(execfile, 0);
155
156   args1 = alloca (strlen(execfile) + strlen(args) + 2);
157
158   if (execfile[0] == '\0')
159
160     /* It is empty.  We need to quote it somehow, or else the target
161        will think there is no argument being passed here.  According
162        to the UDI spec it is quoted "according to TIP OS rules" which
163        I guess means quoting it like the Unix shell should work
164        (sounds pretty bogus to me...).  In fact it doesn't work (with
165        isstip anyway), but passing in two quotes as the argument seems
166        like a reasonable enough behavior anyway (I guess).  */
167
168     strcpy (args1, "''");
169   else
170     strcpy (args1, execfile);
171   strcat (args1, " ");
172   strcat (args1, args);
173
174   UDIInitializeProcess (address_ranges,         /* ProcessMemory[] */
175                         (UDIInt)2,              /* NumberOfRanges */
176                         entry,                  /* EntryPoint */
177                         stack_sizes,            /* *StackSizes */
178                         (UDIInt)2,              /* NumberOfStacks */
179                         args1);                 /* ArgString */
180
181   init_wait_for_inferior ();
182   clear_proceed_status ();
183   proceed (-1, TARGET_SIGNAL_DEFAULT, 0);
184 }
185
186 static void
187 udi_mourn()
188 {
189 #if 0
190   /* Requiring "target udi" each time you run is a major pain.  I suspect
191      this was just blindy copied from remote.c, in which "target" and
192      "run" are combined.  Having a udi target without an inferior seems
193      to work between "target udi" and "run", so why not now?  */
194   pop_target ();                /* Pop back to no-child state */
195 #endif
196   /* But if we're going to want to run it again, we better remove the
197      breakpoints...  */
198   remove_breakpoints ();
199   generic_mourn_inferior ();
200 }
201
202 /******************************************************************** UDI_OPEN
203 ** Open a connection to remote TIP.
204    NAME is the socket domain used for communication with the TIP,
205    then a space and the socket name or TIP-host name.
206    '<udi_udi_config_id>' for example.
207  */
208
209 /* XXX - need cleanups for udiconnect for various failures!!! */
210
211 static void
212 udi_open (name, from_tty)
213      char *name;
214      int from_tty;
215 {
216   unsigned int prl;
217   char *p;
218   int cnt;
219   UDIMemoryRange KnownMemory[10];
220   UDIUInt32 ChipVersions[10];
221   UDIInt NumberOfRanges = 10;
222   UDIInt NumberOfChips = 10;
223   UDIPId PId;
224   UDIUInt32 TIPId, TargetId, DFEId, DFE, TIP, DFEIPCId, TIPIPCId;
225
226   target_preopen(from_tty);
227
228   entry.Offset = 0;
229
230   for (cnt = 0; cnt < BKPT_TABLE_SIZE; cnt++)
231     bkpt_table[cnt].Type = 0;
232
233   if (udi_config_id)
234     free (udi_config_id);
235
236   if (!name)
237     error("Usage: target udi config_id, where config_id appears in udi_soc file");
238
239   udi_config_id = strdup (strtok (name, " \t"));
240
241   if (UDIConnect (udi_config_id, &udi_session_id))
242     /* FIXME: Should set udi_session_id to -1 here.  */
243     error("UDIConnect() failed: %s\n", dfe_errmsg);
244
245   push_target (&udi_ops);
246
247   /*
248   ** Initialize target configuration structure (global)
249   */
250   if (UDIGetTargetConfig (KnownMemory, &NumberOfRanges,
251                           ChipVersions, &NumberOfChips))
252     error ("UDIGetTargetConfig() failed");
253   if (NumberOfChips > 2)
254     fprintf_unfiltered(gdb_stderr,"Target has more than one processor\n");
255   for (cnt=0; cnt < NumberOfRanges; cnt++)
256     {
257       switch(KnownMemory[cnt].Space)
258         {
259         default:
260           fprintf_unfiltered(gdb_stderr, "UDIGetTargetConfig() unknown memory space\n");
261           break;
262         case UDI29KCP_S:
263           break;
264         case UDI29KIROMSpace:
265           RMemStart = KnownMemory[cnt].Offset;
266           RMemSize = KnownMemory[cnt].Size;
267           break;
268         case UDI29KIRAMSpace:
269           IMemStart = KnownMemory[cnt].Offset;
270           IMemSize = KnownMemory[cnt].Size;
271           break;
272         case UDI29KDRAMSpace:
273           DMemStart = KnownMemory[cnt].Offset;
274           DMemSize = KnownMemory[cnt].Size;
275           break;
276         }
277     }
278
279   a29k_get_processor_type ();
280
281   if (UDICreateProcess (&PId))
282      fprintf_unfiltered(gdb_stderr, "UDICreateProcess() failed\n");
283
284   /* Print out some stuff, letting the user now what's going on */
285   if (UDICapabilities (&TIPId, &TargetId, DFEId, DFE, &TIP, &DFEIPCId,
286                        &TIPIPCId, sbuf))
287     error ("UDICapabilities() failed");
288   if (from_tty)
289     {
290       printf_filtered ("Connected via UDI socket,\n\
291  DFE-IPC version %x.%x.%x  TIP-IPC version %x.%x.%x  TIP version %x.%x.%x\n %s\n",
292                        (DFEIPCId>>8)&0xf, (DFEIPCId>>4)&0xf, DFEIPCId&0xf,
293                        (TIPIPCId>>8)&0xf, (TIPIPCId>>4)&0xf, TIPIPCId&0xf,
294                        (TargetId>>8)&0xf, (TargetId>>4)&0xf, TargetId&0xf,
295                        sbuf);
296     }
297 }
298
299 /******************************************************************* UDI_CLOSE
300    Close the open connection to the TIP process.
301    Use this when you want to detach and do something else
302    with your gdb.  */
303 static void
304 udi_close (quitting)    /*FIXME: how is quitting used */
305      int quitting;
306 {
307   if (udi_session_id < 0)
308     return;
309
310   /* We should never get here if there isn't something valid in
311      udi_session_id.  */
312
313   if (UDIDisconnect (udi_session_id, UDITerminateSession))
314     {
315       if (quitting)
316         warning ("UDIDisconnect() failed in udi_close");
317       else
318         error ("UDIDisconnect() failed in udi_close");
319     }
320
321   /* Do not try to close udi_session_id again, later in the program.  */
322   udi_session_id = -1;
323   inferior_pid = 0;
324
325   printf_filtered ("  Ending remote debugging\n");
326
327
328 /**************************************************************** UDI_ATACH */
329 /* Attach to a program that is already loaded and running 
330  * Upon exiting the process's execution is stopped.
331  */
332 static void
333 udi_attach (args, from_tty)
334      char *args;
335      int from_tty;
336 {
337   UDIResource   From;
338   UDIInt32      PC_adds;
339   UDICount      Count = 1;
340   UDISizeT      Size = 4;
341   UDICount      CountDone;
342   UDIBool       HostEndian = 0;
343   UDIError      err;
344
345   if (args == NULL)
346     error_no_arg ("program to attach");
347
348   if (udi_session_id < 0)
349       error ("UDI connection not opened yet, use the 'target udi' command.\n");
350         
351   if (from_tty)
352       printf_unfiltered ("Attaching to remote program %s...\n", prog_name);
353
354   UDIStop();
355   From.Space = UDI29KSpecialRegs;
356   From.Offset = 11;
357   if (err = UDIRead(From, &PC_adds, Count, Size, &CountDone, HostEndian))
358     error ("UDIRead failed in udi_attach");
359   printf_unfiltered ("Remote process is now halted, pc1 = 0x%x.\n", PC_adds);
360 }
361 /************************************************************* UDI_DETACH */
362 /* Terminate the open connection to the TIP process.
363    Use this when you want to detach and do something else
364    with your gdb.  Leave remote process running (with no breakpoints set). */
365 static void
366 udi_detach (args,from_tty)
367      char *args;
368      int from_tty;
369 {
370
371   remove_breakpoints();         /* Just in case there were any left in */
372
373   if (UDIDisconnect (udi_session_id, UDIContinueSession))
374     error ("UDIDisconnect() failed in udi_detach");
375
376   /* Don't try to UDIDisconnect it again in udi_close, which is called from
377      pop_target.  */
378   udi_session_id = -1;
379   inferior_pid = 0;
380
381   pop_target();
382
383   if (from_tty)
384     printf_unfiltered ("Detaching from TIP\n");
385 }
386
387
388 /****************************************************************** UDI_RESUME
389 ** Tell the remote machine to resume.  */
390
391 static void
392 udi_resume (pid, step, sig)
393      int pid, step;
394      enum target_signal sig;
395 {
396   UDIError tip_error;
397   UDIUInt32 Steps = 1;
398   UDIStepType StepType = UDIStepNatural;
399   UDIRange Range;
400
401   if (step)                     /* step 1 instruction */
402     {
403       tip_error = UDIStep (Steps, StepType, Range);
404       if (!tip_error)
405         return;
406
407       fprintf_unfiltered (gdb_stderr,  "UDIStep() error = %d\n", tip_error);
408       error ("failed in udi_resume");
409     }
410
411   if (UDIExecute())
412     error ("UDIExecute() failed in udi_resume");
413 }
414
415 /******************************************************************** UDI_WAIT
416 ** Wait until the remote machine stops, then return,
417    storing status in STATUS just as `wait' would.  */
418
419 static int
420 udi_wait (pid, status)
421      int pid;
422      struct target_waitstatus *status;
423 {
424   UDIInt32      MaxTime;
425   UDIPId        PId;
426   UDIInt32      StopReason;
427   UDISizeT      CountDone;
428   int           old_timeout = timeout;
429   int           old_immediate_quit = immediate_quit;
430   int           i;
431
432   status->kind = TARGET_WAITKIND_EXITED;
433   status->value.integer = 0;
434
435 /* wait for message to arrive. It should be:
436   If the target stops executing, udi_wait() should return.
437 */
438   timeout = 0;                  /* Wait indefinetly for a message */
439   immediate_quit = 1;           /* Helps ability to QUIT */
440
441   while(1)
442     {
443       i = 0;
444       MaxTime = UDIWaitForever;
445       UDIWait(MaxTime, &PId, &StopReason);
446       QUIT;                     /* Let user quit if they want */
447
448       switch (StopReason & UDIGrossState)
449         {
450         case UDIStdoutReady:
451           if (UDIGetStdout (sbuf, (UDISizeT)SBUF_MAX, &CountDone))
452             /* This is said to happen if the program tries to output
453                a whole bunch of output (more than SBUF_MAX, I would
454                guess).  It doesn't seem to happen with the simulator.  */
455             warning ("UDIGetStdout() failed in udi_wait");
456           fwrite (sbuf, 1, CountDone, gdb_stdout);
457           gdb_flush(gdb_stdout);
458           continue;
459
460         case UDIStderrReady:
461           UDIGetStderr (sbuf, (UDISizeT)SBUF_MAX, &CountDone);
462           fwrite (sbuf, 1, CountDone, gdb_stderr);
463           gdb_flush(gdb_stderr);
464           continue;
465
466         case UDIStdinNeeded:
467           {
468             int ch;
469             i = 0;
470             do
471               {
472                 ch = getchar ();
473                 if (ch == EOF)
474                   break;
475                 sbuf[i++] = ch;
476               } while (i < SBUF_MAX && ch != '\n');
477             UDIPutStdin (sbuf, (UDISizeT)i, &CountDone);
478             continue;
479           }
480
481         case UDIRunning:
482           /* In spite of the fact that we told UDIWait to wait forever, it will
483              return spuriously sometimes.  */
484         case UDIStdinModeX:
485           continue;
486         default:
487           break;
488         }
489       break;
490     }
491
492   switch (StopReason & UDIGrossState)
493     {
494     case UDITrapped:
495       printf_unfiltered("Am290*0 received vector number %d\n", StopReason >> 24);
496           
497       switch (StopReason >> 8)
498         {
499         case 0:                 /* Illegal opcode */
500           printf_unfiltered("   (break point)\n");
501           status->kind = TARGET_WAITKIND_STOPPED;
502           status->value.sig = TARGET_SIGNAL_TRAP;
503           break;
504         case 1:                 /* Unaligned Access */
505           status->kind = TARGET_WAITKIND_STOPPED;
506           status->value.sig = TARGET_SIGNAL_BUS;
507           break;
508         case 3:
509         case 4:
510           status->kind = TARGET_WAITKIND_STOPPED;
511           status->value.sig = TARGET_SIGNAL_FPE;
512           break;
513         case 5:                 /* Protection Violation */
514           status->kind = TARGET_WAITKIND_STOPPED;
515           /* Why not SEGV?  What is a Protection Violation?  */
516           status->value.sig = TARGET_SIGNAL_ILL;
517           break;
518         case 6:
519         case 7:
520         case 8:                 /* User Instruction Mapping Miss */
521         case 9:                 /* User Data Mapping Miss */
522         case 10:                /* Supervisor Instruction Mapping Miss */
523         case 11:                /* Supervisor Data Mapping Miss */
524           status->kind = TARGET_WAITKIND_STOPPED;
525           status->value.sig = TARGET_SIGNAL_SEGV;
526           break;
527         case 12:
528         case 13:
529           status->kind = TARGET_WAITKIND_STOPPED;
530           status->value.sig = TARGET_SIGNAL_ILL;
531           break;
532         case 14:                /* Timer */
533           status->kind = TARGET_WAITKIND_STOPPED;
534           status->value.sig = TARGET_SIGNAL_ALRM;
535           break;
536         case 15:                /* Trace */
537           status->kind = TARGET_WAITKIND_STOPPED;
538           status->value.sig = TARGET_SIGNAL_TRAP;
539           break;
540         case 16:                /* INTR0 */
541         case 17:                /* INTR1 */
542         case 18:                /* INTR2 */
543         case 19:                /* INTR3/Internal */
544         case 20:                /* TRAP0 */
545         case 21:                /* TRAP1 */
546           status->kind = TARGET_WAITKIND_STOPPED;
547           status->value.sig = TARGET_SIGNAL_INT;
548           break;
549         case 22:                /* Floating-Point Exception */
550           status->kind = TARGET_WAITKIND_STOPPED;
551           /* Why not FPE?  */
552           status->value.sig = TARGET_SIGNAL_ILL;
553           break;
554         case 77:                /* assert 77 */
555           status->kind = TARGET_WAITKIND_STOPPED;
556           status->value.sig = TARGET_SIGNAL_TRAP;
557           break;
558         default:
559           status->kind = TARGET_WAITKIND_EXITED;
560           status->value.integer = 0;
561         }
562       break;
563     case UDINotExecuting:
564       status->kind = TARGET_WAITKIND_STOPPED;
565       status->value.sig = TARGET_SIGNAL_TERM;
566       break;
567     case UDIStopped:
568       status->kind = TARGET_WAITKIND_STOPPED;
569       status->value.sig = TARGET_SIGNAL_TSTP;
570       break;
571     case UDIWarned:
572       status->kind = TARGET_WAITKIND_STOPPED;
573       status->value.sig = TARGET_SIGNAL_URG;
574       break;
575     case UDIStepped:
576     case UDIBreak:
577       status->kind = TARGET_WAITKIND_STOPPED;
578       status->value.sig = TARGET_SIGNAL_TRAP;
579       break;
580     case UDIWaiting:
581       status->kind = TARGET_WAITKIND_STOPPED;
582       status->value.sig = TARGET_SIGNAL_STOP;
583       break;
584     case UDIHalted:
585       status->kind = TARGET_WAITKIND_STOPPED;
586       status->value.sig = TARGET_SIGNAL_KILL;
587       break;
588     case UDIExited:
589     default:
590       status->kind = TARGET_WAITKIND_EXITED;
591       status->value.integer = 0;
592     }
593
594   timeout = old_timeout;        /* Restore original timeout value */
595   immediate_quit = old_immediate_quit;
596   return inferior_pid;
597 }
598
599 #if 0
600 /* Handy for debugging */
601 udi_pc()
602 {
603   UDIResource   From;
604   UDIUInt32     *To;
605   UDICount      Count;
606   UDISizeT      Size = 4;
607   UDICount      CountDone;
608   UDIBool       HostEndian = 0;
609   UDIError      err;
610   int pc[2];
611   unsigned long myregs[256];
612   int i;
613
614   From.Space = UDI29KPC;
615   From.Offset = 0;
616   To = (UDIUInt32 *)pc;
617   Count = 2;
618
619   err = UDIRead(From, To, Count, Size, &CountDone, HostEndian);
620
621   printf_unfiltered ("err = %d, CountDone = %d, pc[0] = 0x%x, pc[1] = 0x%x\n",
622           err, CountDone, pc[0], pc[1]);
623
624   udi_fetch_registers(-1);
625
626   printf_unfiltered("other pc1 = 0x%x, pc0 = 0x%x\n", *(int *)&registers[4 * PC_REGNUM],
627           *(int *)&registers[4 * NPC_REGNUM]);
628
629   /* Now, read all the registers globally */
630
631   From.Space = UDI29KGlobalRegs;
632   From.Offset = 0;
633   err = UDIRead(From, myregs, 256, 4, &CountDone, HostEndian);
634
635   printf ("err = %d, CountDone = %d\n", err, CountDone);
636
637   printf("\n");
638
639   for (i = 0; i < 256; i += 2)
640     printf("%d:\t%#10x\t%11d\t%#10x\t%11d\n", i, myregs[i], myregs[i],
641            myregs[i+1], myregs[i+1]);
642   printf("\n");
643
644   return pc[0];
645 }
646 #endif
647
648 /********************************************************** UDI_FETCH_REGISTERS
649  * Read a remote register 'regno'. 
650  * If regno==-1 then read all the registers.
651  */
652 static void 
653 udi_fetch_registers (regno)
654 int     regno;
655 {
656   UDIResource   From;
657   UDIUInt32     *To;
658   UDICount      Count;
659   UDISizeT      Size = 4;
660   UDICount      CountDone;
661   UDIBool       HostEndian = 0;
662   UDIError      err;
663   int           i;
664
665   if (regno >= 0)  {
666     fetch_register(regno);
667     return;
668   }
669
670 /* Gr1/rsp */
671
672   From.Space = UDI29KGlobalRegs;
673   From.Offset = 1;
674   To = (UDIUInt32 *)&registers[4 * GR1_REGNUM];
675   Count = 1;
676   if (err = UDIRead(From, To, Count, Size, &CountDone, HostEndian))
677     error("UDIRead() failed in udi_fetch_registers");
678
679   register_valid[GR1_REGNUM] = 1;
680
681 #if defined(GR64_REGNUM)        /* Read gr64-127 */
682
683 /* Global Registers gr64-gr95 */ 
684
685   From.Space = UDI29KGlobalRegs;
686   From.Offset = 64;
687   To = (UDIUInt32 *)&registers[4 * GR64_REGNUM];
688   Count = 32;
689   if (err = UDIRead(From, To, Count, Size, &CountDone, HostEndian))
690     error("UDIRead() failed in udi_fetch_registers");
691
692   for (i = GR64_REGNUM; i < GR64_REGNUM + 32; i++)
693     register_valid[i] = 1;
694
695 #endif  /*  GR64_REGNUM */
696
697 /* Global Registers gr96-gr127 */ 
698
699   From.Space = UDI29KGlobalRegs;
700   From.Offset = 96;
701   To = (UDIUInt32 *)&registers[4 * GR96_REGNUM];
702   Count = 32;
703   if (err = UDIRead(From, To, Count, Size, &CountDone, HostEndian))
704     error("UDIRead() failed in udi_fetch_registers");
705
706   for (i = GR96_REGNUM; i < GR96_REGNUM + 32; i++)
707     register_valid[i] = 1;
708
709 /* Local Registers */
710
711   From.Space = UDI29KLocalRegs;
712   From.Offset = 0;
713   To = (UDIUInt32 *)&registers[4 * LR0_REGNUM];
714   Count = 128;
715   if (err = UDIRead(From, To, Count, Size, &CountDone, HostEndian))
716     error("UDIRead() failed in udi_fetch_registers");
717
718   for (i = LR0_REGNUM; i < LR0_REGNUM + 128; i++)
719     register_valid[i] = 1;
720
721 /* Protected Special Registers */
722
723   From.Space = UDI29KSpecialRegs;
724   From.Offset = 0;
725   To = (UDIUInt32 *)&registers[4 * SR_REGNUM(0)];
726   Count = 15;
727   if (err = UDIRead(From, To, Count, Size, &CountDone, HostEndian))
728     error("UDIRead() failed in udi_fetch_registers");
729
730   for (i = SR_REGNUM(0); i < SR_REGNUM(0) + 15; i++)
731     register_valid[i] = 1;
732
733   if (USE_SHADOW_PC) {  /* Let regno_to_srnum() handle the register number */
734     fetch_register(NPC_REGNUM);
735     fetch_register(PC_REGNUM);
736     fetch_register(PC2_REGNUM);
737
738 /* Unprotected Special Registers sr128-sr135 */
739
740     From.Space = UDI29KSpecialRegs;
741     From.Offset = 128;
742     To = (UDIUInt32 *)&registers[4 * SR_REGNUM(128)];
743     Count = 135-128 + 1;
744     if (err = UDIRead(From, To, Count, Size, &CountDone, HostEndian))
745       error("UDIRead() failed in udi_fetch_registers");
746
747     for (i = SR_REGNUM(128); i < SR_REGNUM(128) + 135-128+1; i++)
748       register_valid[i] = 1;
749   }
750
751   if (remote_debug)
752     {
753       printf_unfiltered("Fetching all registers\n");
754       printf_unfiltered("Fetching PC0 = 0x%x, PC1 = 0x%x, PC2 = 0x%x\n",
755              read_register(NPC_REGNUM), read_register(PC_REGNUM),
756              read_register(PC2_REGNUM));
757     }
758
759   /* There doesn't seem to be any way to get these.  */
760   {
761     int val = -1;
762     supply_register (FPE_REGNUM, (char *) &val);
763     supply_register (INTE_REGNUM, (char *) &val);
764     supply_register (FPS_REGNUM, (char *) &val);
765     supply_register (EXO_REGNUM, (char *) &val);
766   }
767 }
768
769
770 /********************************************************* UDI_STORE_REGISTERS
771 ** Store register regno into the target.  
772  * If regno==-1 then store all the registers.
773  */
774
775 static void
776 udi_store_registers (regno)
777 int regno;
778 {
779   UDIUInt32     *From;
780   UDIResource   To;
781   UDICount      Count;
782   UDISizeT      Size = 4;
783   UDICount      CountDone;
784   UDIBool       HostEndian = 0;
785   
786   if (regno >= 0)
787     {
788       store_register(regno);
789       return;
790     }
791
792   if (remote_debug)
793     {
794       printf_unfiltered("Storing all registers\n");
795       printf_unfiltered("PC0 = 0x%x, PC1 = 0x%x, PC2 = 0x%x\n", read_register(NPC_REGNUM),
796              read_register(PC_REGNUM), read_register(PC2_REGNUM));
797     }
798
799 /* Gr1/rsp */
800
801   From = (UDIUInt32 *)&registers[4 * GR1_REGNUM];
802   To.Space = UDI29KGlobalRegs;
803   To.Offset = 1;
804   Count = 1;
805   if(UDIWrite(From, To, Count, Size, &CountDone, HostEndian))
806     error("UDIWrite() failed in udi_store_regisetrs");
807
808 #if defined(GR64_REGNUM)
809
810 /* Global registers gr64-gr95 */
811
812   From = (UDIUInt32 *)&registers[4 * GR64_REGNUM];
813   To.Space = UDI29KGlobalRegs;
814   To.Offset = 64;
815   Count = 32;
816   if(UDIWrite(From, To, Count, Size, &CountDone, HostEndian))
817     error("UDIWrite() failed in udi_store_regisetrs");
818
819 #endif  /* GR64_REGNUM */
820
821 /* Global registers gr96-gr127 */
822
823   From = (UDIUInt32 *)&registers[4 * GR96_REGNUM];
824   To.Space = UDI29KGlobalRegs;
825   To.Offset = 96;
826   Count = 32;
827   if(UDIWrite(From, To, Count, Size, &CountDone, HostEndian))
828     error("UDIWrite() failed in udi_store_regisetrs");
829
830 /* Local Registers */
831
832   From = (UDIUInt32 *)&registers[4 * LR0_REGNUM];
833   To.Space = UDI29KLocalRegs;
834   To.Offset = 0;
835   Count = 128;
836   if(UDIWrite(From, To, Count, Size, &CountDone, HostEndian))
837     error("UDIWrite() failed in udi_store_regisetrs");
838
839
840 /* Protected Special Registers */ /* VAB through TMR */
841
842   From = (UDIUInt32 *)&registers[4 * SR_REGNUM(0)];
843   To.Space = UDI29KSpecialRegs;
844   To.Offset = 0;
845   Count = 10;
846   if(UDIWrite(From, To, Count, Size, &CountDone, HostEndian))
847     error("UDIWrite() failed in udi_store_regisetrs");
848
849 /* PC0, PC1, PC2 possibly as shadow registers */
850
851   From = (UDIUInt32 *)&registers[4 * SR_REGNUM(10)];
852   To.Space = UDI29KSpecialRegs;
853   Count = 3;
854   if (USE_SHADOW_PC) 
855     To.Offset = 20;                             /* SPC0 */
856   else 
857     To.Offset = 10;                             /* PC0 */
858   if(UDIWrite(From, To, Count, Size, &CountDone, HostEndian))
859     error("UDIWrite() failed in udi_store_regisetrs");
860
861 /* PC1 via UDI29KPC */
862
863   From = (UDIUInt32 *)&registers[4 * PC_REGNUM];
864   To.Space = UDI29KPC;
865   To.Offset = 0;                                /* PC1 */
866   Count = 1;
867   if (UDIWrite (From, To, Count, Size, &CountDone, HostEndian))
868     error ("UDIWrite() failed in udi_store_regisetrs");
869
870   /* LRU and MMU */
871
872   From = (UDIUInt32 *)&registers[4 * SR_REGNUM(13)];
873   To.Space = UDI29KSpecialRegs;
874   To.Offset = 13;
875   Count = 2;
876   if(UDIWrite(From, To, Count, Size, &CountDone, HostEndian))
877     error("UDIWrite() failed in udi_store_regisetrs");
878
879 /* Unprotected Special Registers */ 
880
881   From = (UDIUInt32 *)&registers[4 * SR_REGNUM(128)];
882   To.Space = UDI29KSpecialRegs;
883   To.Offset = 128;
884   Count = 135-128 +1;
885   if(UDIWrite(From, To, Count, Size, &CountDone, HostEndian))
886     error("UDIWrite() failed in udi_store_regisetrs");
887
888   registers_changed ();
889 }
890
891 /****************************************************** UDI_PREPARE_TO_STORE */
892 /* Get ready to modify the registers array.  On machines which store
893    individual registers, this doesn't need to do anything.  On machines
894    which store all the registers in one fell swoop, this makes sure
895    that registers contains all the registers from the program being
896    debugged.  */
897
898 static void
899 udi_prepare_to_store ()
900 {
901   /* Do nothing, since we can store individual regs */
902 }
903
904 /********************************************************** TRANSLATE_ADDR */
905 static CORE_ADDR
906 translate_addr(addr)
907 CORE_ADDR addr;
908 {
909 #if defined(ULTRA3) && defined(KERNEL_DEBUGGING)
910         /* Check for a virtual address in the kernel */
911         /* Assume physical address of ublock is in  paddr_u register */
912         /* FIXME: doesn't work for user virtual addresses */
913         if (addr >= UVADDR) {
914                 /* PADDR_U register holds the physical address of the ublock */
915                 CORE_ADDR i = (CORE_ADDR)read_register(PADDR_U_REGNUM);
916                 return(i + addr - (CORE_ADDR)UVADDR);
917         } else {
918                 return(addr);
919         }
920 #else
921         return(addr);
922 #endif
923 }
924 /************************************************* UDI_XFER_INFERIOR_MEMORY */
925 /* FIXME!  Merge these two.  */
926 static int
927 udi_xfer_inferior_memory (memaddr, myaddr, len, write)
928      CORE_ADDR memaddr;
929      char *myaddr;
930      int len;
931      int write;
932 {
933
934   memaddr = translate_addr(memaddr);
935
936   if (write)
937     return udi_write_inferior_memory (memaddr, myaddr, len);
938   else
939     return udi_read_inferior_memory (memaddr, myaddr, len);
940 }
941
942 /********************************************************** UDI_FILES_INFO */
943 static void
944 udi_files_info ()
945 {
946   printf_unfiltered ("\tAttached to UDI socket to %s", udi_config_id);
947   if (prog_name != NULL)
948     printf_unfiltered ("and running program %s", prog_name);
949   printf_unfiltered (".\n");
950 }
951
952 /**************************************************** UDI_INSERT_BREAKPOINT */
953 static int
954 udi_insert_breakpoint (addr, contents_cache)
955      CORE_ADDR addr;
956      char *contents_cache;
957 {
958   int cnt;
959   UDIError err;
960
961   for (cnt = 0; cnt < BKPT_TABLE_SIZE; cnt++)
962     if (bkpt_table[cnt].Type == 0) /* Find first free slot */
963       break;
964
965   if(cnt >= BKPT_TABLE_SIZE)
966     error("Too many breakpoints set");
967
968   bkpt_table[cnt].Addr.Offset = addr;
969   bkpt_table[cnt].Addr.Space  = UDI29KIRAMSpace;
970   bkpt_table[cnt].PassCount = 1;
971   bkpt_table[cnt].Type = UDIBreakFlagExecute;
972   
973   err = UDISetBreakpoint(bkpt_table[cnt].Addr,
974                          bkpt_table[cnt].PassCount,
975                          bkpt_table[cnt].Type,
976                          &bkpt_table[cnt].BreakId);
977
978   if (err == 0) return 0;               /* Success */
979
980   bkpt_table[cnt].Type = 0;
981   error("UDISetBreakpoint returned error code %d\n", err);
982 }
983
984 /**************************************************** UDI_REMOVE_BREAKPOINT */
985 static int
986 udi_remove_breakpoint (addr, contents_cache)
987      CORE_ADDR addr;
988      char *contents_cache;
989 {
990   int cnt;
991   UDIError err;
992
993   for (cnt = 0; cnt < BKPT_TABLE_SIZE; cnt++)
994     if (bkpt_table[cnt].Addr.Offset == addr) /* Find matching breakpoint */
995       break;
996
997   if(cnt >= BKPT_TABLE_SIZE)
998     error("Can't find breakpoint in table");
999
1000   bkpt_table[cnt].Type = 0;
1001
1002   err = UDIClearBreakpoint(bkpt_table[cnt].BreakId);
1003   if (err == 0) return 0;       /* Success */
1004
1005   error("UDIClearBreakpoint returned error code %d\n", err);
1006 }
1007
1008 static void
1009 udi_kill(arg,from_tty)
1010      char *arg;
1011      int from_tty;
1012 {
1013
1014 #if 0
1015 /*
1016 UDIStop does not really work as advertised.  It causes the TIP to close it's
1017 connection, which usually results in GDB dying with a SIGPIPE.  For now, we
1018 just invoke udi_close, which seems to get things right.
1019 */
1020   UDIStop();
1021
1022   udi_session_id = -1;
1023   inferior_pid = 0;
1024
1025   if (from_tty)
1026     printf_unfiltered("Target has been stopped.");
1027 #endif /* 0 */
1028 #if 0
1029   udi_close(0);
1030   pop_target();
1031 #endif /* 0 */
1032
1033   /* Keep the target around, e.g. so "run" can do the right thing when
1034      we are already debugging something.  */
1035
1036   if (UDIDisconnect (udi_session_id, UDITerminateSession))
1037     {
1038       warning ("UDIDisconnect() failed");
1039     }
1040
1041   /* Do not try to close udi_session_id again, later in the program.  */
1042   udi_session_id = -1;
1043   inferior_pid = 0;
1044 }
1045
1046 /* 
1047    Load a program into the target.  Args are: `program {options}'.  The options
1048    are used to control loading of the program, and are NOT passed onto the
1049    loaded code as arguments.  (You need to use the `run' command to do that.)
1050
1051    The options are:
1052                 -ms %d  Set mem stack size to %d
1053                 -rs %d  Set regular stack size to %d
1054                 -i      send init info (default)
1055                 -noi    don't send init info
1056                 -[tT]   Load Text section
1057                 -[dD]   Load Data section
1058                 -[bB]   Load BSS section
1059                 -[lL]   Load Lit section
1060   */
1061
1062 static void
1063 download(load_arg_string, from_tty)
1064      char *load_arg_string;
1065      int from_tty;
1066 {
1067 #define DEFAULT_MEM_STACK_SIZE          0x6000
1068 #define DEFAULT_REG_STACK_SIZE          0x2000
1069
1070   char *token;
1071   char *filename;
1072   asection *section;
1073   bfd *pbfd;
1074   UDIError err;
1075   int load_text = 1, load_data = 1, load_bss = 1, load_lit = 1;
1076
1077   address_ranges[0].Space = UDI29KIRAMSpace;
1078   address_ranges[0].Offset = 0xffffffff;
1079   address_ranges[0].Size = 0;
1080
1081   address_ranges[1].Space = UDI29KDRAMSpace;
1082   address_ranges[1].Offset = 0xffffffff;
1083   address_ranges[1].Size = 0;
1084
1085   stack_sizes[0] = DEFAULT_REG_STACK_SIZE;
1086   stack_sizes[1] = DEFAULT_MEM_STACK_SIZE;
1087
1088   dont_repeat ();
1089
1090   filename = strtok(load_arg_string, " \t");
1091   if (!filename)
1092     error ("Must specify at least a file name with the load command");
1093
1094   filename = tilde_expand (filename);
1095   make_cleanup (free, filename);
1096
1097   while (token = strtok (NULL, " \t"))
1098     {
1099       if (token[0] == '-')
1100         {
1101           token++;
1102
1103           if (STREQ (token, "ms"))
1104             stack_sizes[1] = atol (strtok (NULL, " \t"));
1105           else if (STREQ (token, "rs"))
1106             stack_sizes[0] = atol (strtok (NULL, " \t"));
1107           else
1108             {
1109               load_text = load_data = load_bss = load_lit = 0;
1110
1111               while (*token)
1112                 {
1113                   switch (*token++)
1114                     {
1115                     case 't':
1116                     case 'T':
1117                       load_text = 1;
1118                       break;
1119                     case 'd':
1120                     case 'D':
1121                       load_data = 1;
1122                       break;
1123                     case 'b':
1124                     case 'B':
1125                       load_bss = 1;
1126                       break;
1127                     case 'l':
1128                     case 'L':
1129                       load_lit = 1;
1130                       break;
1131                     default:
1132                       error ("Unknown UDI load option -%s", token-1);
1133                     }
1134                 }
1135             }
1136         }
1137     }
1138
1139   pbfd = bfd_openr (filename, gnutarget);
1140
1141   if (!pbfd) 
1142     perror_with_name (filename);
1143   
1144   make_cleanup (bfd_close, pbfd);
1145
1146   QUIT;
1147   immediate_quit++;
1148
1149   if (!bfd_check_format (pbfd, bfd_object)) 
1150     error ("It doesn't seem to be an object file");
1151   
1152   for (section = pbfd->sections; section; section = section->next) 
1153     {
1154       if (bfd_get_section_flags (pbfd, section) & SEC_ALLOC)
1155         {
1156           UDIResource To;
1157           UDICount Count;
1158           unsigned long section_size, section_end;
1159           const char *section_name;
1160
1161           section_name = bfd_get_section_name (pbfd, section);
1162           if (STREQ (section_name, ".text") && !load_text)
1163             continue;
1164           else if (STREQ (section_name, ".data") && !load_data)
1165             continue;
1166           else if (STREQ (section_name, ".bss") && !load_bss)
1167             continue;
1168           else if (STREQ (section_name, ".lit") && !load_lit)
1169             continue;
1170
1171           To.Offset = bfd_get_section_vma (pbfd, section);
1172           section_size = bfd_section_size (pbfd, section);
1173           section_end = To.Offset + section_size;
1174
1175           if (section_size == 0)
1176             /* This is needed at least in the BSS case, where the code
1177                below starts writing before it even checks the size.  */
1178             continue;
1179
1180           printf_unfiltered("[Loading section %s at %x (%d bytes)]\n",
1181                  section_name,
1182                  To.Offset,
1183                  section_size);
1184
1185           if (bfd_get_section_flags (pbfd, section) & SEC_CODE)
1186             {
1187               To.Space = UDI29KIRAMSpace;
1188
1189               address_ranges[0].Offset = min (address_ranges[0].Offset,
1190                                               To.Offset);
1191               address_ranges[0].Size = max (address_ranges[0].Size,
1192                                             section_end
1193                                             - address_ranges[0].Offset);
1194             }
1195           else
1196             {
1197               To.Space = UDI29KDRAMSpace;
1198
1199               address_ranges[1].Offset = min (address_ranges[1].Offset,
1200                                               To.Offset);
1201               address_ranges[1].Size = max (address_ranges[1].Size,
1202                                             section_end
1203                                             - address_ranges[1].Offset);
1204             }
1205
1206           if (bfd_get_section_flags (pbfd, section) & SEC_LOAD) /* Text, data or lit */
1207             {
1208               file_ptr fptr;
1209
1210               fptr = 0;
1211
1212               while (section_size > 0)
1213                 {
1214                   char buffer[1024];
1215
1216                   Count = min (section_size, 1024);
1217
1218                   bfd_get_section_contents (pbfd, section, buffer, fptr,
1219                                             Count);
1220
1221                   err = UDIWrite ((UDIHostMemPtr)buffer, /* From */
1222                                   To,                   /* To */
1223                                   Count,                /* Count */
1224                                   (UDISizeT)1,          /* Size */
1225                                   &Count,               /* CountDone */
1226                                   (UDIBool)0);          /* HostEndian */
1227                   if (err)
1228                     error ("UDIWrite failed, error = %d", err);
1229
1230                   To.Offset += Count;
1231                   fptr += Count;
1232                   section_size -= Count;
1233                 }
1234             }
1235           else                  /* BSS */
1236             {
1237               UDIResource From;
1238               unsigned long zero = 0;
1239
1240               /* Write a zero byte at the vma */
1241               /* FIXME: Broken for sections of 1-3 bytes (we test for
1242                  zero above).  */
1243               err = UDIWrite ((UDIHostMemPtr)&zero,     /* From */
1244                               To,                       /* To */
1245                               (UDICount)1,              /* Count */
1246                               (UDISizeT)4,              /* Size */
1247                               &Count,                   /* CountDone */
1248                               (UDIBool)0);              /* HostEndian */
1249               if (err)
1250                 error ("UDIWrite failed, error = %d", err);
1251
1252               From = To;
1253               To.Offset+=4;
1254
1255               /* Now, duplicate it for the length of the BSS */
1256               err = UDICopy (From,                      /* From */
1257                              To,                        /* To */
1258                              (UDICount)(section_size/4 - 1), /* Count */
1259                              (UDISizeT)4,               /* Size */
1260                              &Count,                    /* CountDone */
1261                              (UDIBool)1);               /* Direction */
1262               if (err)
1263                 {
1264                   char message[100];
1265                   int xerr;
1266
1267                   xerr = UDIGetErrorMsg(err, 100, message, &Count);
1268                   if (!xerr)
1269                     fprintf_unfiltered (gdb_stderr, "Error is %s\n", message);
1270                   else
1271                     fprintf_unfiltered (gdb_stderr, "xerr is %d\n", xerr);
1272                   error ("UDICopy failed, error = %d", err);
1273                 }
1274             }
1275
1276         }
1277     }
1278
1279   entry.Space = UDI29KIRAMSpace;
1280   entry.Offset = bfd_get_start_address (pbfd);
1281   
1282   immediate_quit--;
1283 }
1284
1285 /* User interface to download an image into the remote target.  See download()
1286  * for details on args.
1287  */
1288
1289 static void
1290 udi_load(args, from_tty)
1291      char *args;
1292      int from_tty;
1293 {
1294   download (args, from_tty);
1295
1296   symbol_file_add (strtok (args, " \t"), from_tty, 0, 0, 0, 0);
1297
1298   /* Getting new symbols may change our opinion about what is
1299      frameless.  */
1300   reinit_frame_cache ();
1301 }
1302
1303 /*************************************************** UDI_WRITE_INFERIOR_MEMORY
1304 ** Copy LEN bytes of data from debugger memory at MYADDR
1305    to inferior's memory at MEMADDR.  Returns number of bytes written.  */
1306 static int
1307 udi_write_inferior_memory (memaddr, myaddr, len)
1308      CORE_ADDR memaddr;
1309      char *myaddr;
1310      int len;
1311 {
1312   int           nwritten = 0;
1313   UDIUInt32     *From;
1314   UDIResource   To;
1315   UDICount      Count;
1316   UDISizeT      Size = 1;
1317   UDICount      CountDone = 0;
1318   UDIBool       HostEndian = 0;
1319   
1320   To.Space = udi_memory_space(memaddr);
1321   From = (UDIUInt32*)myaddr;
1322
1323   while (nwritten < len)
1324   {     Count = len - nwritten;
1325         if (Count > MAXDATA) Count = MAXDATA;
1326         To.Offset = memaddr + nwritten;
1327         if(UDIWrite(From, To, Count, Size, &CountDone, HostEndian))
1328         {  error("UDIWrite() failed in udi_write_inferior_memory");
1329            break;       
1330         }
1331         else
1332         {  nwritten += CountDone;
1333            From += CountDone;
1334         }
1335   }
1336   return(nwritten);
1337 }
1338
1339 /**************************************************** UDI_READ_INFERIOR_MEMORY
1340 ** Read LEN bytes from inferior memory at MEMADDR.  Put the result
1341    at debugger address MYADDR.  Returns number of bytes read.  */
1342 static int
1343 udi_read_inferior_memory(memaddr, myaddr, len)
1344      CORE_ADDR memaddr;
1345      char *myaddr;
1346      int len;
1347 {
1348   int           nread = 0;
1349   UDIResource   From;
1350   UDIUInt32     *To;
1351   UDICount      Count;
1352   UDISizeT      Size = 1;
1353   UDICount      CountDone = 0;
1354   UDIBool       HostEndian = 0;
1355   UDIError      err;
1356   
1357   From.Space = udi_memory_space(memaddr);       
1358   To = (UDIUInt32*)myaddr;
1359
1360   while (nread < len)
1361   {     Count = len - nread;
1362         if (Count > MAXDATA) Count = MAXDATA;
1363         From.Offset = memaddr + nread;
1364         if(err = UDIRead(From, To, Count, Size, &CountDone, HostEndian))
1365         {  error("UDIRead() failed in udi_read_inferior_memory");
1366            break;       
1367         }
1368         else
1369         {  nread += CountDone;
1370            To += CountDone;
1371         }
1372   }
1373   return(nread);
1374 }
1375
1376 /********************************************************************* WARNING
1377 */
1378 udi_warning(num)
1379 int     num;
1380 {
1381     error ("ERROR while loading program into remote TIP: $d\n", num);
1382 }
1383
1384
1385 /*****************************************************************************/ 
1386 /* Fetch a single register indicatated by 'regno'. 
1387  * Returns 0/-1 on success/failure.  
1388  */
1389 static void
1390 fetch_register (regno)
1391      int regno;
1392 {
1393   UDIResource   From;
1394   UDIUInt32     To;
1395   UDICount      Count = 1;
1396   UDISizeT      Size = 4;
1397   UDICount      CountDone;
1398   UDIBool       HostEndian = 0;
1399   UDIError      err;
1400   int           result;
1401
1402   if (regno == GR1_REGNUM)
1403     {
1404       From.Space = UDI29KGlobalRegs;
1405       From.Offset = 1;
1406     }
1407   else if (regno >= GR96_REGNUM && regno < GR96_REGNUM + 32)
1408     {
1409       From.Space = UDI29KGlobalRegs;
1410       From.Offset = (regno - GR96_REGNUM) + 96;;
1411     }
1412
1413 #if defined(GR64_REGNUM)
1414
1415   else if (regno >= GR64_REGNUM && regno < GR64_REGNUM + 32 )
1416     {
1417       From.Space = UDI29KGlobalRegs;
1418       From.Offset = (regno - GR64_REGNUM) + 64;
1419     }
1420
1421 #endif  /* GR64_REGNUM */
1422
1423   else if (regno >= LR0_REGNUM && regno < LR0_REGNUM + 128)
1424     {
1425       From.Space = UDI29KLocalRegs;
1426       From.Offset = (regno - LR0_REGNUM);
1427     }
1428   else if (regno>=FPE_REGNUM && regno<=EXO_REGNUM)  
1429     {
1430       int val = -1;
1431       supply_register(160 + (regno - FPE_REGNUM),(char *) &val);
1432       return;           /* Pretend Success */
1433     }
1434   else 
1435     {
1436       From.Space = UDI29KSpecialRegs;
1437       From.Offset = regnum_to_srnum(regno); 
1438     }
1439
1440   if (err = UDIRead(From, &To, Count, Size, &CountDone, HostEndian))
1441     error("UDIRead() failed in udi_fetch_registers");
1442
1443   supply_register(regno, (char *) &To);
1444
1445   if (remote_debug)
1446     printf_unfiltered("Fetching register %s = 0x%x\n", reg_names[regno], To);
1447 }
1448 /*****************************************************************************/ 
1449 /* Store a single register indicated by 'regno'. 
1450  * Returns 0/-1 on success/failure.  
1451  */
1452 static int
1453 store_register (regno)
1454      int regno;
1455 {
1456   int           result;
1457   UDIUInt32     From;
1458   UDIResource   To;
1459   UDICount      Count = 1;
1460   UDISizeT      Size = 4;
1461   UDICount      CountDone;
1462   UDIBool       HostEndian = 0;
1463
1464   From =  read_register (regno);        /* get data value */
1465
1466   if (remote_debug)
1467     printf_unfiltered("Storing register %s = 0x%x\n", reg_names[regno], From);
1468
1469   if (regno == GR1_REGNUM)
1470     {
1471       To.Space = UDI29KGlobalRegs;
1472       To.Offset = 1;
1473       result = UDIWrite(&From, To, Count, Size, &CountDone, HostEndian);
1474       /* Setting GR1 changes the numbers of all the locals, so invalidate the 
1475        * register cache.  Do this *after* calling read_register, because we want 
1476        * read_register to return the value that write_register has just stuffed 
1477        * into the registers array, not the value of the register fetched from 
1478        * the inferior.  
1479        */
1480       registers_changed ();
1481     }
1482 #if defined(GR64_REGNUM)
1483   else if (regno >= GR64_REGNUM && regno < GR64_REGNUM + 32 )
1484     {
1485       To.Space = UDI29KGlobalRegs;
1486       To.Offset = (regno - GR64_REGNUM) + 64;
1487       result = UDIWrite(&From, To, Count, Size, &CountDone, HostEndian);
1488     }
1489 #endif  /* GR64_REGNUM */
1490   else if (regno >= GR96_REGNUM && regno < GR96_REGNUM + 32)
1491     {
1492       To.Space = UDI29KGlobalRegs;
1493       To.Offset = (regno - GR96_REGNUM) + 96;
1494       result = UDIWrite(&From, To, Count, Size, &CountDone, HostEndian);
1495     }
1496   else if (regno >= LR0_REGNUM && regno < LR0_REGNUM + 128)
1497     {
1498       To.Space = UDI29KLocalRegs;
1499       To.Offset = (regno - LR0_REGNUM);
1500       result = UDIWrite(&From, To, Count, Size, &CountDone, HostEndian);
1501     }
1502   else if (regno >= FPE_REGNUM && regno <= EXO_REGNUM)  
1503     return 0;           /* Pretend Success */
1504   else if (regno == PC_REGNUM)
1505     {    
1506       /* PC1 via UDI29KPC */
1507
1508       To.Space = UDI29KPC;
1509       To.Offset = 0;            /* PC1 */
1510       result = UDIWrite (&From, To, Count, Size, &CountDone, HostEndian);
1511
1512       /* Writing to this loc actually changes the values of pc0 & pc1 */
1513
1514       register_valid[PC_REGNUM] = 0; /* pc1 */
1515       register_valid[NPC_REGNUM] = 0; /* pc0 */
1516     }
1517   else  /* An unprotected or protected special register */
1518     {
1519       To.Space = UDI29KSpecialRegs;
1520       To.Offset = regnum_to_srnum(regno); 
1521       result = UDIWrite(&From, To, Count, Size, &CountDone, HostEndian);
1522     }
1523
1524   if (result != 0)
1525     error("UDIWrite() failed in store_registers");
1526
1527   return 0;
1528 }
1529 /********************************************************** REGNUM_TO_SRNUM */
1530 /* 
1531  * Convert a gdb special register number to a 29000 special register number.
1532  */
1533 static int
1534 regnum_to_srnum(regno)
1535 int     regno;
1536 {
1537         switch(regno) {
1538                 case VAB_REGNUM: return(0); 
1539                 case OPS_REGNUM: return(1); 
1540                 case CPS_REGNUM: return(2); 
1541                 case CFG_REGNUM: return(3); 
1542                 case CHA_REGNUM: return(4); 
1543                 case CHD_REGNUM: return(5); 
1544                 case CHC_REGNUM: return(6); 
1545                 case RBP_REGNUM: return(7); 
1546                 case TMC_REGNUM: return(8); 
1547                 case TMR_REGNUM: return(9); 
1548                 case NPC_REGNUM: return(USE_SHADOW_PC ? (20) : (10));
1549                 case PC_REGNUM:  return(USE_SHADOW_PC ? (21) : (11));
1550                 case PC2_REGNUM: return(USE_SHADOW_PC ? (22) : (12));
1551                 case MMU_REGNUM: return(13); 
1552                 case LRU_REGNUM: return(14); 
1553                 case IPC_REGNUM: return(128); 
1554                 case IPA_REGNUM: return(129); 
1555                 case IPB_REGNUM: return(130); 
1556                 case Q_REGNUM:   return(131); 
1557                 case ALU_REGNUM: return(132); 
1558                 case BP_REGNUM:  return(133); 
1559                 case FC_REGNUM:  return(134); 
1560                 case CR_REGNUM:  return(135); 
1561                 case FPE_REGNUM: return(160); 
1562                 case INTE_REGNUM: return(161); 
1563                 case FPS_REGNUM: return(162); 
1564                 case EXO_REGNUM:return(164); 
1565                 default:
1566                         return(255);    /* Failure ? */
1567         }
1568 }
1569 /****************************************************************************/
1570 /*
1571  * Determine the Target memory space qualifier based on the addr. 
1572  * FIXME: Can't distinguis I_ROM/D_ROM.  
1573  * FIXME: Doesn't know anything about I_CACHE/D_CACHE.
1574  */
1575 static CPUSpace
1576 udi_memory_space(addr)
1577 CORE_ADDR       addr;
1578 {
1579         UDIUInt32 tstart = IMemStart;
1580         UDIUInt32 tend   = tstart + IMemSize;  
1581         UDIUInt32 dstart = DMemStart;
1582         UDIUInt32 dend   = tstart + DMemSize;  
1583         UDIUInt32 rstart = RMemStart;
1584         UDIUInt32 rend   = tstart + RMemSize;  
1585
1586         if (((UDIUInt32)addr >= tstart) && ((UDIUInt32)addr < tend)) { 
1587                 return UDI29KIRAMSpace;
1588         } else if (((UDIUInt32)addr >= dstart) && ((UDIUInt32)addr < dend)) { 
1589                 return UDI29KDRAMSpace;
1590         } else if (((UDIUInt32)addr >= rstart) && ((UDIUInt32)addr < rend)) {
1591                 /* FIXME: how do we determine between D_ROM and I_ROM */
1592                 return UDI29KIROMSpace;
1593         } else  /* FIXME: what do me do now? */
1594                 return UDI29KDRAMSpace; /* Hmmm! */
1595 }
1596 /*********************************************************************** STUBS
1597 */
1598
1599 void  convert16() {;}
1600 void  convert32() {;}
1601 GDB_FILE * EchoFile = 0;                /* used for debugging */
1602 int   QuietMode = 0;            /* used for debugging */
1603 \f
1604 #ifdef NO_HIF_SUPPORT
1605 service_HIF(msg)
1606      union msg_t *msg;
1607 {
1608   return(0);                    /* Emulate a failure */
1609 }
1610 #endif
1611 \f
1612 /* Target_ops vector.  Not static because there does not seem to be
1613    any portable way to do a forward declaration of a static variable.
1614    The RS/6000 doesn't like "extern" followed by "static"; SunOS
1615    /bin/cc doesn't like "static" twice.  */
1616
1617 struct target_ops udi_ops = {
1618         "udi",
1619         "Remote UDI connected TIP",
1620         "Remote debug an AMD 29k using UDI socket connection to TIP process.\n\
1621 Arguments are\n\
1622 `configuration-id AF_INET hostname port-number'\n\
1623     To connect via the network, where hostname and port-number specify the\n\
1624     host and port where you can connect via UDI.\n\
1625     configuration-id is unused.\n\
1626 \n\
1627 `configuration-id AF_UNIX socket-name tip-program'\n\
1628     To connect using a local connection to the \"tip.exe\" program which is\n\
1629     supplied by AMD.  If socket-name specifies an AF_UNIX socket then the\n\
1630     tip program must already be started; connect to it using that socket.\n\
1631     If not, start up tip-program, which should be the name of the tip\n\
1632     program.  If appropriate, the PATH environment variable is searched.\n\
1633     configuration-id is unused.\n\
1634 \n\
1635 `configuration-id'\n\
1636     Look up the configuration in ./udi_soc or /etc/udi_soc, which\n\
1637     are files containing lines in the above formats.  configuration-id is\n\
1638     used to pick which line of the file to use.",
1639         udi_open,
1640         udi_close,
1641         udi_attach,
1642         udi_detach,
1643         udi_resume,
1644         udi_wait,
1645         udi_fetch_registers,
1646         udi_store_registers,
1647         udi_prepare_to_store,
1648         udi_xfer_inferior_memory,
1649         udi_files_info,
1650         udi_insert_breakpoint,
1651         udi_remove_breakpoint,
1652         0,                      /* termial_init */
1653         0,                      /* terminal_inferior */
1654         0,                      /* terminal_ours_for_output */
1655         0,                      /* terminal_ours */
1656         0,                      /* terminal_info */
1657         udi_kill,               /* FIXME, kill */
1658         udi_load,
1659         0,                      /* lookup_symbol */
1660         udi_create_inferior,
1661         udi_mourn,              /* mourn_inferior FIXME */
1662         0,                      /* can_run */
1663         0,                      /* notice_signals */
1664         process_stratum,
1665         0,                      /* next */
1666         1,                      /* has_all_memory */
1667         1,                      /* has_memory */
1668         1,                      /* has_stack */
1669         1,                      /* has_registers */
1670         1,                      /* has_execution */
1671         0,                      /* sections */
1672         0,                      /* sections_end */
1673         OPS_MAGIC,              /* Always the last thing */
1674 };
1675
1676 void
1677 _initialize_remote_udi ()
1678 {
1679   add_target (&udi_ops);
1680 }