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