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