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