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