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