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