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