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