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