Fri Jan 7 11:26:29 1994 Stan Shebs (shebs@andros.cygnus.com)
[deliverable/binutils-gdb.git] / gdb / remote-udi.c
CommitLineData
15ee4caa 1/* Remote debugging interface for AMD 29k interfaced via UDI, for GDB.
5140562f
JG
2 Copyright 1990, 1992 Free Software Foundation, Inc.
3 Written by Daniel Mann. Contributed by AMD.
9bddba9a
SG
4
5This file is part of GDB.
6
7This program is free software; you can redistribute it and/or modify
8it under the terms of the GNU General Public License as published by
5140562f
JG
9the Free Software Foundation; either version 2 of the License, or
10(at your option) any later version.
9bddba9a
SG
11
12This program is distributed in the hope that it will be useful,
13but WITHOUT ANY WARRANTY; without even the implied warranty of
14MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15GNU General Public License for more details.
16
17You should have received a copy of the GNU General Public License
5140562f
JG
18along with this program; if not, write to the Free Software
19Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
9bddba9a 20
15ee4caa
JG
21/* This is like remote.c but uses the Universal Debug Interface (UDI) to
22 talk to the target hardware (or simulator). UDI is a TCP/IP based
23 protocol; for hardware that doesn't run TCP, an interface adapter
24 daemon talks UDI on one side, and talks to the hardware (typically
25 over a serial port) on the other side.
26
27 - Originally written by Daniel Mann at AMD for MiniMON and gdb 3.91.6.
5140562f
JG
28 - David Wood (wood@lab.ultra.nyu.edu) at New York University adapted this
29 file to gdb 3.95. I was unable to get this working on sun3os4
157ea89d 30 with termio, only with sgtty.
15ee4caa 31 - Daniel Mann at AMD took the 3.95 adaptions above and replaced
5140562f
JG
32 MiniMON interface with UDI-p interface. */
33
9bddba9a
SG
34#include "defs.h"
35#include "inferior.h"
36#include "wait.h"
37#include "value.h"
38#include <ctype.h>
39#include <fcntl.h>
40#include <signal.h>
41#include <errno.h>
42#include <string.h>
43#include "terminal.h"
44#include "target.h"
aa942355 45#include "29k-share/udi/udiproc.h"
aa1dea48 46#include "gdbcmd.h"
b6113cc4 47#include "bfd.h"
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 ();
45dc9be3 170 proceed (-1, TARGET_SIGNAL_DEFAULT, 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 363udi_resume (pid, step, sig)
67ac9759
JK
364 int pid, step;
365 enum target_signal sig;
9bddba9a 366{
aa1dea48
SG
367 UDIError tip_error;
368 UDIUInt32 Steps = 1;
369 UDIStepType StepType = UDIStepNatural;
370 UDIRange Range;
836e343b 371
9bddba9a 372 if (step) /* step 1 instruction */
aa1dea48
SG
373 {
374 tip_error = UDIStep (Steps, StepType, Range);
375 if (!tip_error)
376 return;
9bddba9a 377
199b2450 378 fprintf_unfiltered (gdb_stderr, "UDIStep() error = %d\n", tip_error);
aa1dea48
SG
379 error ("failed in udi_resume");
380 }
381
382 if (UDIExecute())
383 error ("UDIExecute() failed in udi_resume");
9bddba9a
SG
384}
385
386/******************************************************************** UDI_WAIT
387** Wait until the remote machine stops, then return,
388 storing status in STATUS just as `wait' would. */
389
390static int
de43d7d0
SG
391udi_wait (pid, status)
392 int pid;
67ac9759 393 struct target_waitstatus *status;
9bddba9a
SG
394{
395 UDIInt32 MaxTime;
396 UDIPId PId;
397 UDIInt32 StopReason;
398 UDISizeT CountDone;
399 int old_timeout = timeout;
400 int old_immediate_quit = immediate_quit;
401 int i;
402
67ac9759
JK
403 status->kind = TARGET_WAITKIND_EXITED;
404 status->value.integer = 0;
9bddba9a
SG
405
406/* wait for message to arrive. It should be:
407 If the target stops executing, udi_wait() should return.
408*/
409 timeout = 0; /* Wait indefinetly for a message */
410 immediate_quit = 1; /* Helps ability to QUIT */
aa1dea48 411
9bddba9a 412 while(1)
9bddba9a 413 {
aa1dea48
SG
414 i = 0;
415 MaxTime = UDIWaitForever;
416 UDIWait(MaxTime, &PId, &StopReason);
417 QUIT; /* Let user quit if they want */
418
419 switch (StopReason & UDIGrossState)
420 {
7fb95139
JK
421 case UDIStdoutReady:
422 if (UDIGetStdout (sbuf, (UDISizeT)SBUF_MAX, &CountDone))
83f00e88
JK
423 /* This is said to happen if the program tries to output
424 a whole bunch of output (more than SBUF_MAX, I would
425 guess). It doesn't seem to happen with the simulator. */
7fb95139 426 warning ("UDIGetStdout() failed in udi_wait");
199b2450
TL
427 fwrite (sbuf, 1, CountDone, gdb_stdout);
428 gdb_flush(gdb_stdout);
aa1dea48 429 continue;
7fb95139
JK
430
431 case UDIStderrReady:
432 UDIGetStderr (sbuf, (UDISizeT)SBUF_MAX, &CountDone);
199b2450
TL
433 fwrite (sbuf, 1, CountDone, gdb_stderr);
434 gdb_flush(gdb_stderr);
aa1dea48 435 continue;
5c303f64 436
aa1dea48 437 case UDIStdinNeeded:
5c303f64
JK
438 {
439 int ch;
440 i = 0;
441 do
442 {
443 ch = getchar ();
444 if (ch == EOF)
445 break;
446 sbuf[i++] = ch;
447 } while (i < SBUF_MAX && ch != '\n');
448 UDIPutStdin (sbuf, (UDISizeT)i, &CountDone);
449 continue;
450 }
451
7c86126f
SG
452 case UDIRunning:
453 /* In spite of the fact that we told UDIWait to wait forever, it will
454 return spuriously sometimes. */
aa1dea48
SG
455 case UDIStdinModeX:
456 continue;
457 default:
458 break;
459 }
460 break;
9bddba9a 461 }
aa1dea48
SG
462
463 switch (StopReason & UDIGrossState)
464 {
465 case UDITrapped:
199b2450 466 printf_unfiltered("Am290*0 received vector number %d\n", StopReason >> 24);
aa1dea48
SG
467
468 switch (StopReason >> 8)
469 {
470 case 0: /* Illegal opcode */
199b2450 471 printf_unfiltered(" (break point)\n");
67ac9759
JK
472 status->kind = TARGET_WAITKIND_STOPPED;
473 status->value.sig = TARGET_SIGNAL_TRAP;
aa1dea48
SG
474 break;
475 case 1: /* Unaligned Access */
67ac9759
JK
476 status->kind = TARGET_WAITKIND_STOPPED;
477 status->value.sig = TARGET_SIGNAL_BUS;
aa1dea48
SG
478 break;
479 case 3:
480 case 4:
67ac9759
JK
481 status->kind = TARGET_WAITKIND_STOPPED;
482 status->value.sig = TARGET_SIGNAL_FPE;
aa1dea48
SG
483 break;
484 case 5: /* Protection Violation */
67ac9759
JK
485 status->kind = TARGET_WAITKIND_STOPPED;
486 /* Why not SEGV? What is a Protection Violation? */
487 status->value.sig = TARGET_SIGNAL_ILL;
aa1dea48
SG
488 break;
489 case 6:
490 case 7:
491 case 8: /* User Instruction Mapping Miss */
492 case 9: /* User Data Mapping Miss */
493 case 10: /* Supervisor Instruction Mapping Miss */
494 case 11: /* Supervisor Data Mapping Miss */
67ac9759
JK
495 status->kind = TARGET_WAITKIND_STOPPED;
496 status->value.sig = TARGET_SIGNAL_SEGV;
aa1dea48
SG
497 break;
498 case 12:
499 case 13:
67ac9759
JK
500 status->kind = TARGET_WAITKIND_STOPPED;
501 status->value.sig = TARGET_SIGNAL_ILL;
aa1dea48
SG
502 break;
503 case 14: /* Timer */
67ac9759
JK
504 status->kind = TARGET_WAITKIND_STOPPED;
505 status->value.sig = TARGET_SIGNAL_ALRM;
aa1dea48
SG
506 break;
507 case 15: /* Trace */
67ac9759
JK
508 status->kind = TARGET_WAITKIND_STOPPED;
509 status->value.sig = TARGET_SIGNAL_TRAP;
aa1dea48
SG
510 break;
511 case 16: /* INTR0 */
512 case 17: /* INTR1 */
513 case 18: /* INTR2 */
514 case 19: /* INTR3/Internal */
515 case 20: /* TRAP0 */
516 case 21: /* TRAP1 */
67ac9759
JK
517 status->kind = TARGET_WAITKIND_STOPPED;
518 status->value.sig = TARGET_SIGNAL_INT;
aa1dea48
SG
519 break;
520 case 22: /* Floating-Point Exception */
67ac9759
JK
521 status->kind = TARGET_WAITKIND_STOPPED;
522 /* Why not FPE? */
523 status->value.sig = TARGET_SIGNAL_ILL;
aa1dea48
SG
524 break;
525 case 77: /* assert 77 */
67ac9759
JK
526 status->kind = TARGET_WAITKIND_STOPPED;
527 status->value.sig = TARGET_SIGNAL_TRAP;
aa1dea48
SG
528 break;
529 default:
67ac9759
JK
530 status->kind = TARGET_WAITKIND_EXITED;
531 status->value.integer = 0;
aa1dea48
SG
532 }
533 break;
534 case UDINotExecuting:
67ac9759
JK
535 status->kind = TARGET_WAITKIND_STOPPED;
536 status->value.sig = TARGET_SIGNAL_TERM;
aa1dea48 537 break;
aa1dea48 538 case UDIStopped:
67ac9759
JK
539 status->kind = TARGET_WAITKIND_STOPPED;
540 status->value.sig = TARGET_SIGNAL_TSTP;
aa1dea48
SG
541 break;
542 case UDIWarned:
67ac9759
JK
543 status->kind = TARGET_WAITKIND_STOPPED;
544 status->value.sig = TARGET_SIGNAL_URG;
aa1dea48
SG
545 break;
546 case UDIStepped:
547 case UDIBreak:
67ac9759
JK
548 status->kind = TARGET_WAITKIND_STOPPED;
549 status->value.sig = TARGET_SIGNAL_TRAP;
aa1dea48
SG
550 break;
551 case UDIWaiting:
67ac9759
JK
552 status->kind = TARGET_WAITKIND_STOPPED;
553 status->value.sig = TARGET_SIGNAL_STOP;
aa1dea48
SG
554 break;
555 case UDIHalted:
67ac9759
JK
556 status->kind = TARGET_WAITKIND_STOPPED;
557 status->value.sig = TARGET_SIGNAL_KILL;
aa1dea48
SG
558 break;
559 case UDIExited:
560 default:
67ac9759
JK
561 status->kind = TARGET_WAITKIND_EXITED;
562 status->value.integer = 0;
aa1dea48 563 }
9bddba9a
SG
564
565 timeout = old_timeout; /* Restore original timeout value */
566 immediate_quit = old_immediate_quit;
f8f6b2c7 567 return inferior_pid;
9bddba9a
SG
568}
569
cadd2c6f
SG
570#if 0
571/* Handy for debugging */
572udi_pc()
573{
574 UDIResource From;
575 UDIUInt32 *To;
576 UDICount Count;
577 UDISizeT Size = 4;
578 UDICount CountDone;
579 UDIBool HostEndian = 0;
580 UDIError err;
581 int pc[2];
b58a1973
SG
582 unsigned long myregs[256];
583 int i;
cadd2c6f
SG
584
585 From.Space = UDI29KPC;
586 From.Offset = 0;
587 To = (UDIUInt32 *)pc;
588 Count = 2;
589
590 err = UDIRead(From, To, Count, Size, &CountDone, HostEndian);
591
199b2450 592 printf_unfiltered ("err = %d, CountDone = %d, pc[0] = 0x%x, pc[1] = 0x%x\n",
cadd2c6f
SG
593 err, CountDone, pc[0], pc[1]);
594
595 udi_fetch_registers(-1);
596
199b2450 597 printf_unfiltered("other pc1 = 0x%x, pc0 = 0x%x\n", *(int *)&registers[4 * PC_REGNUM],
cadd2c6f
SG
598 *(int *)&registers[4 * NPC_REGNUM]);
599
b58a1973
SG
600 /* Now, read all the registers globally */
601
602 From.Space = UDI29KGlobalRegs;
603 From.Offset = 0;
604 err = UDIRead(From, myregs, 256, 4, &CountDone, HostEndian);
605
606 printf ("err = %d, CountDone = %d\n", err, CountDone);
607
608 printf("\n");
609
610 for (i = 0; i < 256; i += 2)
611 printf("%d:\t%#10x\t%11d\t%#10x\t%11d\n", i, myregs[i], myregs[i],
612 myregs[i+1], myregs[i+1]);
613 printf("\n");
614
cadd2c6f
SG
615 return pc[0];
616}
617#endif
618
9bddba9a
SG
619/********************************************************** UDI_FETCH_REGISTERS
620 * Read a remote register 'regno'.
621 * If regno==-1 then read all the registers.
622 */
623static void
624udi_fetch_registers (regno)
625int regno;
626{
627 UDIResource From;
628 UDIUInt32 *To;
629 UDICount Count;
630 UDISizeT Size = 4;
631 UDICount CountDone;
632 UDIBool HostEndian = 0;
b5a3d2aa 633 UDIError err;
9bddba9a
SG
634 int i;
635
636 if (regno >= 0) {
d0b04c6a
SG
637 fetch_register(regno);
638 return;
9bddba9a 639 }
9bddba9a
SG
640
641/* Gr1/rsp */
d0b04c6a 642
9bddba9a
SG
643 From.Space = UDI29KGlobalRegs;
644 From.Offset = 1;
d0b04c6a 645 To = (UDIUInt32 *)&registers[4 * GR1_REGNUM];
9bddba9a 646 Count = 1;
b5a3d2aa 647 if (err = UDIRead(From, To, Count, Size, &CountDone, HostEndian))
9bddba9a 648 error("UDIRead() failed in udi_fetch_registers");
d0b04c6a
SG
649
650 register_valid[GR1_REGNUM] = 1;
9bddba9a
SG
651
652#if defined(GR64_REGNUM) /* Read gr64-127 */
d0b04c6a 653
9bddba9a 654/* Global Registers gr64-gr95 */
d0b04c6a 655
9bddba9a
SG
656 From.Space = UDI29KGlobalRegs;
657 From.Offset = 64;
d0b04c6a 658 To = (UDIUInt32 *)&registers[4 * GR64_REGNUM];
9bddba9a 659 Count = 32;
b5a3d2aa 660 if (err = UDIRead(From, To, Count, Size, &CountDone, HostEndian))
9bddba9a 661 error("UDIRead() failed in udi_fetch_registers");
d0b04c6a
SG
662
663 for (i = GR64_REGNUM; i < GR64_REGNUM + 32; i++)
664 register_valid[i] = 1;
665
9bddba9a
SG
666#endif /* GR64_REGNUM */
667
668/* Global Registers gr96-gr127 */
d0b04c6a 669
9bddba9a 670 From.Space = UDI29KGlobalRegs;
d0b04c6a
SG
671 From.Offset = 96;
672 To = (UDIUInt32 *)&registers[4 * GR96_REGNUM];
9bddba9a 673 Count = 32;
b5a3d2aa 674 if (err = UDIRead(From, To, Count, Size, &CountDone, HostEndian))
9bddba9a 675 error("UDIRead() failed in udi_fetch_registers");
9bddba9a 676
d0b04c6a
SG
677 for (i = GR96_REGNUM; i < GR96_REGNUM + 32; i++)
678 register_valid[i] = 1;
679
680/* Local Registers */
681
9bddba9a
SG
682 From.Space = UDI29KLocalRegs;
683 From.Offset = 0;
d0b04c6a 684 To = (UDIUInt32 *)&registers[4 * LR0_REGNUM];
9bddba9a 685 Count = 128;
b5a3d2aa 686 if (err = UDIRead(From, To, Count, Size, &CountDone, HostEndian))
9bddba9a 687 error("UDIRead() failed in udi_fetch_registers");
9bddba9a 688
d0b04c6a
SG
689 for (i = LR0_REGNUM; i < LR0_REGNUM + 128; i++)
690 register_valid[i] = 1;
691
692/* Protected Special Registers */
693
9bddba9a
SG
694 From.Space = UDI29KSpecialRegs;
695 From.Offset = 0;
d0b04c6a 696 To = (UDIUInt32 *)&registers[4 * SR_REGNUM(0)];
9bddba9a 697 Count = 15;
b5a3d2aa 698 if (err = UDIRead(From, To, Count, Size, &CountDone, HostEndian))
9bddba9a 699 error("UDIRead() failed in udi_fetch_registers");
d0b04c6a
SG
700
701 for (i = SR_REGNUM(0); i < SR_REGNUM(0) + 15; i++)
702 register_valid[i] = 1;
9bddba9a
SG
703
704 if (USE_SHADOW_PC) { /* Let regno_to_srnum() handle the register number */
d0b04c6a
SG
705 fetch_register(NPC_REGNUM);
706 fetch_register(PC_REGNUM);
707 fetch_register(PC2_REGNUM);
9bddba9a 708
d0b04c6a
SG
709/* Unprotected Special Registers sr128-sr135 */
710
711 From.Space = UDI29KSpecialRegs;
9bddba9a 712 From.Offset = 128;
d0b04c6a
SG
713 To = (UDIUInt32 *)&registers[4 * SR_REGNUM(128)];
714 Count = 135-128 + 1;
b5a3d2aa 715 if (err = UDIRead(From, To, Count, Size, &CountDone, HostEndian))
9bddba9a 716 error("UDIRead() failed in udi_fetch_registers");
d0b04c6a
SG
717
718 for (i = SR_REGNUM(128); i < SR_REGNUM(128) + 135-128+1; i++)
719 register_valid[i] = 1;
9bddba9a
SG
720 }
721
d0d8484a 722 if (remote_debug)
aa1dea48 723 {
199b2450
TL
724 printf_unfiltered("Fetching all registers\n");
725 printf_unfiltered("Fetching PC0 = 0x%x, PC1 = 0x%x, PC2 = 0x%x\n",
aa1dea48
SG
726 read_register(NPC_REGNUM), read_register(PC_REGNUM),
727 read_register(PC2_REGNUM));
728 }
729
9bddba9a
SG
730 /* There doesn't seem to be any way to get these. */
731 {
732 int val = -1;
733 supply_register (FPE_REGNUM, (char *) &val);
d0b04c6a 734 supply_register (INTE_REGNUM, (char *) &val);
9bddba9a
SG
735 supply_register (FPS_REGNUM, (char *) &val);
736 supply_register (EXO_REGNUM, (char *) &val);
737 }
9bddba9a
SG
738}
739
740
741/********************************************************* UDI_STORE_REGISTERS
742** Store register regno into the target.
743 * If regno==-1 then store all the registers.
744 */
745
746static void
747udi_store_registers (regno)
748int regno;
749{
750 UDIUInt32 *From;
751 UDIResource To;
752 UDICount Count;
753 UDISizeT Size = 4;
754 UDICount CountDone;
755 UDIBool HostEndian = 0;
756
757 if (regno >= 0)
758 {
759 store_register(regno);
760 return;
761 }
762
d0d8484a 763 if (remote_debug)
aa1dea48 764 {
199b2450
TL
765 printf_unfiltered("Storing all registers\n");
766 printf_unfiltered("PC0 = 0x%x, PC1 = 0x%x, PC2 = 0x%x\n", read_register(NPC_REGNUM),
aa1dea48
SG
767 read_register(PC_REGNUM), read_register(PC2_REGNUM));
768 }
769
9bddba9a 770/* Gr1/rsp */
d0b04c6a
SG
771
772 From = (UDIUInt32 *)&registers[4 * GR1_REGNUM];
9bddba9a
SG
773 To.Space = UDI29KGlobalRegs;
774 To.Offset = 1;
775 Count = 1;
776 if(UDIWrite(From, To, Count, Size, &CountDone, HostEndian))
777 error("UDIWrite() failed in udi_store_regisetrs");
778
779#if defined(GR64_REGNUM)
d0b04c6a 780
9bddba9a 781/* Global registers gr64-gr95 */
d0b04c6a
SG
782
783 From = (UDIUInt32 *)&registers[4 * GR64_REGNUM];
9bddba9a
SG
784 To.Space = UDI29KGlobalRegs;
785 To.Offset = 64;
786 Count = 32;
787 if(UDIWrite(From, To, Count, Size, &CountDone, HostEndian))
788 error("UDIWrite() failed in udi_store_regisetrs");
d0b04c6a 789
9bddba9a
SG
790#endif /* GR64_REGNUM */
791
792/* Global registers gr96-gr127 */
d0b04c6a
SG
793
794 From = (UDIUInt32 *)&registers[4 * GR96_REGNUM];
9bddba9a
SG
795 To.Space = UDI29KGlobalRegs;
796 To.Offset = 96;
797 Count = 32;
798 if(UDIWrite(From, To, Count, Size, &CountDone, HostEndian))
799 error("UDIWrite() failed in udi_store_regisetrs");
800
801/* Local Registers */
d0b04c6a
SG
802
803 From = (UDIUInt32 *)&registers[4 * LR0_REGNUM];
9bddba9a
SG
804 To.Space = UDI29KLocalRegs;
805 To.Offset = 0;
806 Count = 128;
807 if(UDIWrite(From, To, Count, Size, &CountDone, HostEndian))
808 error("UDIWrite() failed in udi_store_regisetrs");
809
810
811/* Protected Special Registers */ /* VAB through TMR */
d0b04c6a
SG
812
813 From = (UDIUInt32 *)&registers[4 * SR_REGNUM(0)];
9bddba9a
SG
814 To.Space = UDI29KSpecialRegs;
815 To.Offset = 0;
816 Count = 10;
817 if(UDIWrite(From, To, Count, Size, &CountDone, HostEndian))
818 error("UDIWrite() failed in udi_store_regisetrs");
819
d0b04c6a
SG
820/* PC0, PC1, PC2 possibly as shadow registers */
821
822 From = (UDIUInt32 *)&registers[4 * SR_REGNUM(10)];
9bddba9a
SG
823 To.Space = UDI29KSpecialRegs;
824 Count = 3;
825 if (USE_SHADOW_PC)
826 To.Offset = 20; /* SPC0 */
827 else
828 To.Offset = 10; /* PC0 */
829 if(UDIWrite(From, To, Count, Size, &CountDone, HostEndian))
830 error("UDIWrite() failed in udi_store_regisetrs");
831
cadd2c6f
SG
832/* PC1 via UDI29KPC */
833
834 From = (UDIUInt32 *)&registers[4 * PC_REGNUM];
835 To.Space = UDI29KPC;
836 To.Offset = 0; /* PC1 */
837 Count = 1;
838 if (UDIWrite (From, To, Count, Size, &CountDone, HostEndian))
839 error ("UDIWrite() failed in udi_store_regisetrs");
840
9bddba9a 841 /* LRU and MMU */
d0b04c6a
SG
842
843 From = (UDIUInt32 *)&registers[4 * SR_REGNUM(13)];
9bddba9a
SG
844 To.Space = UDI29KSpecialRegs;
845 To.Offset = 13;
846 Count = 2;
847 if(UDIWrite(From, To, Count, Size, &CountDone, HostEndian))
848 error("UDIWrite() failed in udi_store_regisetrs");
849
850/* Unprotected Special Registers */
d0b04c6a
SG
851
852 From = (UDIUInt32 *)&registers[4 * SR_REGNUM(128)];
9bddba9a
SG
853 To.Space = UDI29KSpecialRegs;
854 To.Offset = 128;
855 Count = 135-128 +1;
856 if(UDIWrite(From, To, Count, Size, &CountDone, HostEndian))
857 error("UDIWrite() failed in udi_store_regisetrs");
858
859 registers_changed ();
9bddba9a
SG
860}
861
862/****************************************************** UDI_PREPARE_TO_STORE */
863/* Get ready to modify the registers array. On machines which store
864 individual registers, this doesn't need to do anything. On machines
865 which store all the registers in one fell swoop, this makes sure
866 that registers contains all the registers from the program being
867 debugged. */
868
869static void
870udi_prepare_to_store ()
871{
872 /* Do nothing, since we can store individual regs */
873}
874
875/********************************************************** TRANSLATE_ADDR */
876static CORE_ADDR
877translate_addr(addr)
878CORE_ADDR addr;
879{
880#if defined(ULTRA3) && defined(KERNEL_DEBUGGING)
881 /* Check for a virtual address in the kernel */
882 /* Assume physical address of ublock is in paddr_u register */
883 /* FIXME: doesn't work for user virtual addresses */
884 if (addr >= UVADDR) {
885 /* PADDR_U register holds the physical address of the ublock */
886 CORE_ADDR i = (CORE_ADDR)read_register(PADDR_U_REGNUM);
887 return(i + addr - (CORE_ADDR)UVADDR);
888 } else {
889 return(addr);
890 }
891#else
892 return(addr);
893#endif
894}
895/************************************************* UDI_XFER_INFERIOR_MEMORY */
896/* FIXME! Merge these two. */
897static int
898udi_xfer_inferior_memory (memaddr, myaddr, len, write)
899 CORE_ADDR memaddr;
900 char *myaddr;
901 int len;
902 int write;
903{
904
905 memaddr = translate_addr(memaddr);
906
907 if (write)
908 return udi_write_inferior_memory (memaddr, myaddr, len);
909 else
910 return udi_read_inferior_memory (memaddr, myaddr, len);
911}
912
913/********************************************************** UDI_FILES_INFO */
914static void
915udi_files_info ()
916{
199b2450 917 printf_unfiltered ("\tAttached to UDI socket to %s and running program %s.\n",
9bddba9a
SG
918 udi_config_id, prog_name);
919}
920
921/**************************************************** UDI_INSERT_BREAKPOINT */
922static int
923udi_insert_breakpoint (addr, contents_cache)
924 CORE_ADDR addr;
925 char *contents_cache;
926{
54847287
SG
927 int cnt;
928 UDIError err;
929
930 for (cnt = 0; cnt < BKPT_TABLE_SIZE; cnt++)
931 if (bkpt_table[cnt].Type == 0) /* Find first free slot */
932 break;
933
934 if(cnt >= BKPT_TABLE_SIZE)
935 error("Too many breakpoints set");
9bddba9a 936
9bddba9a
SG
937 bkpt_table[cnt].Addr.Offset = addr;
938 bkpt_table[cnt].Addr.Space = UDI29KIRAMSpace;
939 bkpt_table[cnt].PassCount = 1;
940 bkpt_table[cnt].Type = UDIBreakFlagExecute;
941
54847287
SG
942 err = UDISetBreakpoint(bkpt_table[cnt].Addr,
943 bkpt_table[cnt].PassCount,
944 bkpt_table[cnt].Type,
945 &bkpt_table[cnt].BreakId);
946
947 if (err == 0) return 0; /* Success */
948
949 bkpt_table[cnt].Type = 0;
950 error("UDISetBreakpoint returned error code %d\n", err);
9bddba9a
SG
951}
952
953/**************************************************** UDI_REMOVE_BREAKPOINT */
954static int
955udi_remove_breakpoint (addr, contents_cache)
956 CORE_ADDR addr;
957 char *contents_cache;
958{
54847287
SG
959 int cnt;
960 UDIError err;
961
962 for (cnt = 0; cnt < BKPT_TABLE_SIZE; cnt++)
963 if (bkpt_table[cnt].Addr.Offset == addr) /* Find matching breakpoint */
964 break;
965
966 if(cnt >= BKPT_TABLE_SIZE)
967 error("Can't find breakpoint in table");
968
9bddba9a
SG
969 bkpt_table[cnt].Type = 0;
970
54847287
SG
971 err = UDIClearBreakpoint(bkpt_table[cnt].BreakId);
972 if (err == 0) return 0; /* Success */
9bddba9a 973
54847287
SG
974 error("UDIClearBreakpoint returned error code %d\n", err);
975}
9bddba9a 976
9bddba9a
SG
977static void
978udi_kill(arg,from_tty)
b6113cc4
SG
979 char *arg;
980 int from_tty;
9bddba9a 981{
9bddba9a 982
b6113cc4
SG
983#if 0
984/*
985UDIStop does not really work as advertised. It causes the TIP to close it's
986connection, which usually results in GDB dying with a SIGPIPE. For now, we
987just invoke udi_close, which seems to get things right.
988*/
989 UDIStop();
9bddba9a 990
b6113cc4
SG
991 udi_session_id = -1;
992 inferior_pid = 0;
9bddba9a 993
b6113cc4 994 if (from_tty)
199b2450 995 printf_unfiltered("Target has been stopped.");
b6113cc4
SG
996#else
997 udi_close(0);
998#endif
999 pop_target();
1000}
9bddba9a 1001
9bddba9a 1002/*
b6113cc4
SG
1003 Load a program into the target. Args are: `program {options}'. The options
1004 are used to control loading of the program, and are NOT passed onto the
1005 loaded code as arguments. (You need to use the `run' command to do that.)
1006
1007 The options are:
1008 -ms %d Set mem stack size to %d
1009 -rs %d Set regular stack size to %d
1010 -i send init info (default)
1011 -noi don't send init info
1012 -[tT] Load Text section
1013 -[dD] Load Data section
1014 -[bB] Load BSS section
1015 -[lL] Load Lit section
1016 */
1017
9bddba9a 1018static void
b6113cc4
SG
1019download(load_arg_string, from_tty)
1020 char *load_arg_string;
1021 int from_tty;
9bddba9a 1022{
b6113cc4
SG
1023#define DEFAULT_MEM_STACK_SIZE 0x6000
1024#define DEFAULT_REG_STACK_SIZE 0x2000
1025
1026 char *token;
1027 char *filename;
1028 asection *section;
1029 bfd *pbfd;
1030 UDIError err;
1031 int load_text = 1, load_data = 1, load_bss = 1, load_lit = 1;
1032
1033 address_ranges[0].Space = UDI29KIRAMSpace;
1034 address_ranges[0].Offset = 0xffffffff;
1035 address_ranges[0].Size = 0;
1036
1037 address_ranges[1].Space = UDI29KDRAMSpace;
1038 address_ranges[1].Offset = 0xffffffff;
1039 address_ranges[1].Size = 0;
1040
1041 stack_sizes[0] = DEFAULT_REG_STACK_SIZE;
1042 stack_sizes[1] = DEFAULT_MEM_STACK_SIZE;
9bddba9a
SG
1043
1044 dont_repeat ();
1045
b6113cc4
SG
1046 filename = strtok(load_arg_string, " \t");
1047 if (!filename)
1048 error ("Must specify at least a file name with the load command");
1049
1050 filename = tilde_expand (filename);
1051 make_cleanup (free, filename);
1052
1053 while (token = strtok (NULL, " \t"))
1054 {
1055 if (token[0] == '-')
1056 {
1057 token++;
1058
2e4964ad 1059 if (STREQ (token, "ms"))
b6113cc4 1060 stack_sizes[1] = atol (strtok (NULL, " \t"));
2e4964ad 1061 else if (STREQ (token, "rs"))
b6113cc4
SG
1062 stack_sizes[0] = atol (strtok (NULL, " \t"));
1063 else
1064 {
1065 load_text = load_data = load_bss = load_lit = 0;
1066
1067 while (*token)
1068 {
1069 switch (*token++)
1070 {
1071 case 't':
1072 case 'T':
1073 load_text = 1;
1074 break;
1075 case 'd':
1076 case 'D':
1077 load_data = 1;
1078 break;
1079 case 'b':
1080 case 'B':
1081 load_bss = 1;
1082 break;
1083 case 'l':
1084 case 'L':
1085 load_lit = 1;
1086 break;
1087 default:
1088 error ("Unknown UDI load option -%s", token-1);
1089 }
1090 }
1091 }
1092 }
9bddba9a 1093 }
b6113cc4 1094
0685d95f 1095 pbfd = bfd_openr (filename, gnutarget);
b6113cc4
SG
1096
1097 if (!pbfd)
1098 perror_with_name (filename);
1099
1100 make_cleanup (bfd_close, pbfd);
1101
9bddba9a
SG
1102 QUIT;
1103 immediate_quit++;
b6113cc4
SG
1104
1105 if (!bfd_check_format (pbfd, bfd_object))
1106 error ("It doesn't seem to be an object file");
1107
1108 for (section = pbfd->sections; section; section = section->next)
1109 {
1110 if (bfd_get_section_flags (pbfd, section) & SEC_ALLOC)
1111 {
1112 UDIResource To;
1113 UDICount Count;
1114 unsigned long section_size, section_end;
1115 const char *section_name;
1116
1117 section_name = bfd_get_section_name (pbfd, section);
2e4964ad 1118 if (STREQ (section_name, ".text") && !load_text)
b6113cc4 1119 continue;
2e4964ad 1120 else if (STREQ (section_name, ".data") && !load_data)
b6113cc4 1121 continue;
2e4964ad 1122 else if (STREQ (section_name, ".bss") && !load_bss)
b6113cc4 1123 continue;
2e4964ad 1124 else if (STREQ (section_name, ".lit") && !load_lit)
b6113cc4
SG
1125 continue;
1126
1127 To.Offset = bfd_get_section_vma (pbfd, section);
1128 section_size = bfd_section_size (pbfd, section);
1129 section_end = To.Offset + section_size;
1130
573becd8
JK
1131 if (section_size == 0)
1132 /* This is needed at least in the BSS case, where the code
1133 below starts writing before it even checks the size. */
1134 continue;
1135
199b2450 1136 printf_unfiltered("[Loading section %s at %x (%d bytes)]\n",
b6113cc4
SG
1137 section_name,
1138 To.Offset,
1139 section_size);
1140
1141 if (bfd_get_section_flags (pbfd, section) & SEC_CODE)
1142 {
1143 To.Space = UDI29KIRAMSpace;
1144
1145 address_ranges[0].Offset = min (address_ranges[0].Offset,
1146 To.Offset);
1147 address_ranges[0].Size = max (address_ranges[0].Size,
1148 section_end
1149 - address_ranges[0].Offset);
1150 }
1151 else
1152 {
1153 To.Space = UDI29KDRAMSpace;
1154
1155 address_ranges[1].Offset = min (address_ranges[1].Offset,
1156 To.Offset);
1157 address_ranges[1].Size = max (address_ranges[1].Size,
1158 section_end
1159 - address_ranges[1].Offset);
1160 }
1161
1162 if (bfd_get_section_flags (pbfd, section) & SEC_LOAD) /* Text, data or lit */
1163 {
1164 file_ptr fptr;
1165
1166 fptr = 0;
1167
1168 while (section_size > 0)
1169 {
1170 char buffer[1024];
1171
1172 Count = min (section_size, 1024);
1173
1174 bfd_get_section_contents (pbfd, section, buffer, fptr,
1175 Count);
1176
1177 err = UDIWrite ((UDIHostMemPtr)buffer, /* From */
1178 To, /* To */
1179 Count, /* Count */
1180 (UDISizeT)1, /* Size */
1181 &Count, /* CountDone */
1182 (UDIBool)0); /* HostEndian */
1183 if (err)
1184 error ("UDIWrite failed, error = %d", err);
1185
1186 To.Offset += Count;
1187 fptr += Count;
1188 section_size -= Count;
1189 }
1190 }
1191 else /* BSS */
1192 {
1193 UDIResource From;
b5a3d2aa 1194 unsigned long zero = 0;
b6113cc4
SG
1195
1196 /* Write a zero byte at the vma */
573becd8
JK
1197 /* FIXME: Broken for sections of 1-3 bytes (we test for
1198 zero above). */
b6113cc4
SG
1199 err = UDIWrite ((UDIHostMemPtr)&zero, /* From */
1200 To, /* To */
1201 (UDICount)1, /* Count */
b5a3d2aa 1202 (UDISizeT)4, /* Size */
b6113cc4
SG
1203 &Count, /* CountDone */
1204 (UDIBool)0); /* HostEndian */
1205 if (err)
1206 error ("UDIWrite failed, error = %d", err);
1207
1208 From = To;
b5a3d2aa 1209 To.Offset+=4;
b6113cc4
SG
1210
1211 /* Now, duplicate it for the length of the BSS */
1212 err = UDICopy (From, /* From */
1213 To, /* To */
b5a3d2aa
SG
1214 (UDICount)(section_size/4 - 1), /* Count */
1215 (UDISizeT)4, /* Size */
b6113cc4
SG
1216 &Count, /* CountDone */
1217 (UDIBool)1); /* Direction */
1218 if (err)
b5a3d2aa
SG
1219 {
1220 char message[100];
1221 int xerr;
1222
1223 xerr = UDIGetErrorMsg(err, 100, message, &Count);
1224 if (!xerr)
199b2450 1225 fprintf_unfiltered (gdb_stderr, "Error is %s\n", message);
b5a3d2aa 1226 else
199b2450 1227 fprintf_unfiltered (gdb_stderr, "xerr is %d\n", xerr);
b5a3d2aa
SG
1228 error ("UDICopy failed, error = %d", err);
1229 }
b6113cc4
SG
1230 }
1231
1232 }
1233 }
1234
1235 entry.Space = UDI29KIRAMSpace;
1236 entry.Offset = bfd_get_start_address (pbfd);
1237
9bddba9a 1238 immediate_quit--;
b6113cc4
SG
1239}
1240
1241/* User interface to download an image into the remote target. See download()
1242 * for details on args.
1243 */
1244
1245static void
1246udi_load(args, from_tty)
1247 char *args;
1248 int from_tty;
1249{
1250 download (args, from_tty);
9bddba9a 1251
b6113cc4 1252 symbol_file_add (strtok (args, " \t"), from_tty, 0, 0, 0, 0);
9bddba9a
SG
1253}
1254
1255/*************************************************** UDI_WRITE_INFERIOR_MEMORY
1256** Copy LEN bytes of data from debugger memory at MYADDR
1257 to inferior's memory at MEMADDR. Returns number of bytes written. */
1258static int
1259udi_write_inferior_memory (memaddr, myaddr, len)
1260 CORE_ADDR memaddr;
1261 char *myaddr;
1262 int len;
1263{
1264 int nwritten = 0;
1265 UDIUInt32 *From;
1266 UDIResource To;
1267 UDICount Count;
1268 UDISizeT Size = 1;
1269 UDICount CountDone = 0;
1270 UDIBool HostEndian = 0;
1271
b6113cc4 1272 To.Space = udi_memory_space(memaddr);
9bddba9a
SG
1273 From = (UDIUInt32*)myaddr;
1274
1275 while (nwritten < len)
1276 { Count = len - nwritten;
1277 if (Count > MAXDATA) Count = MAXDATA;
1278 To.Offset = memaddr + nwritten;
1279 if(UDIWrite(From, To, Count, Size, &CountDone, HostEndian))
1280 { error("UDIWrite() failed in udi_write_inferrior_memory");
1281 break;
1282 }
1283 else
1284 { nwritten += CountDone;
1285 From += CountDone;
1286 }
1287 }
9bddba9a
SG
1288 return(nwritten);
1289}
1290
1291/**************************************************** UDI_READ_INFERIOR_MEMORY
1292** Read LEN bytes from inferior memory at MEMADDR. Put the result
1293 at debugger address MYADDR. Returns number of bytes read. */
1294static int
1295udi_read_inferior_memory(memaddr, myaddr, len)
1296 CORE_ADDR memaddr;
1297 char *myaddr;
1298 int len;
1299{
1300 int nread = 0;
1301 UDIResource From;
1302 UDIUInt32 *To;
1303 UDICount Count;
1304 UDISizeT Size = 1;
1305 UDICount CountDone = 0;
1306 UDIBool HostEndian = 0;
b5a3d2aa 1307 UDIError err;
9bddba9a 1308
9bddba9a
SG
1309 From.Space = udi_memory_space(memaddr);
1310 To = (UDIUInt32*)myaddr;
1311
1312 while (nread < len)
1313 { Count = len - nread;
1314 if (Count > MAXDATA) Count = MAXDATA;
1315 From.Offset = memaddr + nread;
b5a3d2aa
SG
1316 if(err = UDIRead(From, To, Count, Size, &CountDone, HostEndian))
1317 { error("UDIRead() failed in udi_read_inferrior_memory");
9bddba9a
SG
1318 break;
1319 }
1320 else
1321 { nread += CountDone;
1322 To += CountDone;
1323 }
1324 }
1325 return(nread);
1326}
1327
1328/********************************************************************* WARNING
1329*/
1330udi_warning(num)
1331int num;
1332{
1333 error ("ERROR while loading program into remote TIP: $d\n", num);
1334}
1335
1336
1337/*****************************************************************************/
1338/* Fetch a single register indicatated by 'regno'.
1339 * Returns 0/-1 on success/failure.
1340 */
aa1dea48 1341static void
9bddba9a
SG
1342fetch_register (regno)
1343 int regno;
1344{
1345 UDIResource From;
1346 UDIUInt32 To;
1347 UDICount Count = 1;
1348 UDISizeT Size = 4;
1349 UDICount CountDone;
1350 UDIBool HostEndian = 0;
b5a3d2aa 1351 UDIError err;
9bddba9a
SG
1352 int result;
1353
9bddba9a 1354 if (regno == GR1_REGNUM)
d0b04c6a
SG
1355 {
1356 From.Space = UDI29KGlobalRegs;
1357 From.Offset = 1;
1358 }
9bddba9a 1359 else if (regno >= GR96_REGNUM && regno < GR96_REGNUM + 32)
d0b04c6a
SG
1360 {
1361 From.Space = UDI29KGlobalRegs;
1362 From.Offset = (regno - GR96_REGNUM) + 96;;
1363 }
1364
9bddba9a 1365#if defined(GR64_REGNUM)
d0b04c6a 1366
9bddba9a 1367 else if (regno >= GR64_REGNUM && regno < GR64_REGNUM + 32 )
d0b04c6a
SG
1368 {
1369 From.Space = UDI29KGlobalRegs;
1370 From.Offset = (regno - GR64_REGNUM) + 64;
1371 }
1372
9bddba9a 1373#endif /* GR64_REGNUM */
d0b04c6a 1374
9bddba9a 1375 else if (regno >= LR0_REGNUM && regno < LR0_REGNUM + 128)
d0b04c6a
SG
1376 {
1377 From.Space = UDI29KLocalRegs;
1378 From.Offset = (regno - LR0_REGNUM);
1379 }
9bddba9a 1380 else if (regno>=FPE_REGNUM && regno<=EXO_REGNUM)
d0b04c6a
SG
1381 {
1382 int val = -1;
1383 supply_register(160 + (regno - FPE_REGNUM),(char *) &val);
aa1dea48 1384 return; /* Pretend Success */
d0b04c6a 1385 }
9bddba9a 1386 else
d0b04c6a
SG
1387 {
1388 From.Space = UDI29KSpecialRegs;
1389 From.Offset = regnum_to_srnum(regno);
1390 }
1391
b5a3d2aa 1392 if (err = UDIRead(From, &To, Count, Size, &CountDone, HostEndian))
9bddba9a 1393 error("UDIRead() failed in udi_fetch_registers");
d0b04c6a 1394
9bddba9a 1395 supply_register(regno, (char *) &To);
aa1dea48 1396
d0d8484a 1397 if (remote_debug)
199b2450 1398 printf_unfiltered("Fetching register %s = 0x%x\n", reg_names[regno], To);
9bddba9a
SG
1399}
1400/*****************************************************************************/
1401/* Store a single register indicated by 'regno'.
1402 * Returns 0/-1 on success/failure.
1403 */
1404static int
1405store_register (regno)
1406 int regno;
1407{
1408 int result;
1409 UDIUInt32 From;
1410 UDIResource To;
1411 UDICount Count = 1;
1412 UDISizeT Size = 4;
1413 UDICount CountDone;
1414 UDIBool HostEndian = 0;
1415
9bddba9a
SG
1416 From = read_register (regno); /* get data value */
1417
d0d8484a 1418 if (remote_debug)
199b2450 1419 printf_unfiltered("Storing register %s = 0x%x\n", reg_names[regno], From);
aa1dea48 1420
9bddba9a 1421 if (regno == GR1_REGNUM)
cadd2c6f
SG
1422 {
1423 To.Space = UDI29KGlobalRegs;
1424 To.Offset = 1;
1425 result = UDIWrite(&From, To, Count, Size, &CountDone, HostEndian);
1426 /* Setting GR1 changes the numbers of all the locals, so invalidate the
1427 * register cache. Do this *after* calling read_register, because we want
1428 * read_register to return the value that write_register has just stuffed
1429 * into the registers array, not the value of the register fetched from
1430 * the inferior.
1431 */
1432 registers_changed ();
1433 }
9bddba9a
SG
1434#if defined(GR64_REGNUM)
1435 else if (regno >= GR64_REGNUM && regno < GR64_REGNUM + 32 )
cadd2c6f
SG
1436 {
1437 To.Space = UDI29KGlobalRegs;
1438 To.Offset = (regno - GR64_REGNUM) + 64;
1439 result = UDIWrite(&From, To, Count, Size, &CountDone, HostEndian);
1440 }
9bddba9a
SG
1441#endif /* GR64_REGNUM */
1442 else if (regno >= GR96_REGNUM && regno < GR96_REGNUM + 32)
cadd2c6f
SG
1443 {
1444 To.Space = UDI29KGlobalRegs;
1445 To.Offset = (regno - GR96_REGNUM) + 96;
1446 result = UDIWrite(&From, To, Count, Size, &CountDone, HostEndian);
1447 }
9bddba9a 1448 else if (regno >= LR0_REGNUM && regno < LR0_REGNUM + 128)
cadd2c6f
SG
1449 {
1450 To.Space = UDI29KLocalRegs;
1451 To.Offset = (regno - LR0_REGNUM);
1452 result = UDIWrite(&From, To, Count, Size, &CountDone, HostEndian);
1453 }
1454 else if (regno >= FPE_REGNUM && regno <= EXO_REGNUM)
9bddba9a 1455 return 0; /* Pretend Success */
cadd2c6f
SG
1456 else if (regno == PC_REGNUM)
1457 {
1458 /* PC1 via UDI29KPC */
1459
1460 To.Space = UDI29KPC;
1461 To.Offset = 0; /* PC1 */
1462 result = UDIWrite (&From, To, Count, Size, &CountDone, HostEndian);
b58a1973
SG
1463
1464 /* Writing to this loc actually changes the values of pc0 & pc1 */
1465
1466 register_valid[PC_REGNUM] = 0; /* pc1 */
1467 register_valid[NPC_REGNUM] = 0; /* pc0 */
cadd2c6f 1468 }
9bddba9a 1469 else /* An unprotected or protected special register */
cadd2c6f
SG
1470 {
1471 To.Space = UDI29KSpecialRegs;
1472 To.Offset = regnum_to_srnum(regno);
1473 result = UDIWrite(&From, To, Count, Size, &CountDone, HostEndian);
1474 }
9bddba9a 1475
cadd2c6f 1476 if (result != 0)
9bddba9a 1477 error("UDIWrite() failed in store_registers");
cadd2c6f
SG
1478
1479 return 0;
9bddba9a
SG
1480}
1481/********************************************************** REGNUM_TO_SRNUM */
1482/*
1483 * Convert a gdb special register number to a 29000 special register number.
1484 */
1485static int
1486regnum_to_srnum(regno)
1487int regno;
1488{
1489 switch(regno) {
1490 case VAB_REGNUM: return(0);
1491 case OPS_REGNUM: return(1);
1492 case CPS_REGNUM: return(2);
1493 case CFG_REGNUM: return(3);
1494 case CHA_REGNUM: return(4);
1495 case CHD_REGNUM: return(5);
1496 case CHC_REGNUM: return(6);
1497 case RBP_REGNUM: return(7);
1498 case TMC_REGNUM: return(8);
1499 case TMR_REGNUM: return(9);
1500 case NPC_REGNUM: return(USE_SHADOW_PC ? (20) : (10));
1501 case PC_REGNUM: return(USE_SHADOW_PC ? (21) : (11));
1502 case PC2_REGNUM: return(USE_SHADOW_PC ? (22) : (12));
1503 case MMU_REGNUM: return(13);
1504 case LRU_REGNUM: return(14);
1505 case IPC_REGNUM: return(128);
1506 case IPA_REGNUM: return(129);
1507 case IPB_REGNUM: return(130);
1508 case Q_REGNUM: return(131);
1509 case ALU_REGNUM: return(132);
1510 case BP_REGNUM: return(133);
1511 case FC_REGNUM: return(134);
1512 case CR_REGNUM: return(135);
1513 case FPE_REGNUM: return(160);
d0b04c6a 1514 case INTE_REGNUM: return(161);
9bddba9a
SG
1515 case FPS_REGNUM: return(162);
1516 case EXO_REGNUM:return(164);
1517 default:
1518 return(255); /* Failure ? */
1519 }
1520}
1521/****************************************************************************/
1522/*
1523 * Determine the Target memory space qualifier based on the addr.
1524 * FIXME: Can't distinguis I_ROM/D_ROM.
1525 * FIXME: Doesn't know anything about I_CACHE/D_CACHE.
1526 */
1527static CPUSpace
1528udi_memory_space(addr)
b6113cc4 1529CORE_ADDR addr;
9bddba9a
SG
1530{
1531 UDIUInt32 tstart = IMemStart;
1532 UDIUInt32 tend = tstart + IMemSize;
1533 UDIUInt32 dstart = DMemStart;
1534 UDIUInt32 dend = tstart + DMemSize;
1535 UDIUInt32 rstart = RMemStart;
1536 UDIUInt32 rend = tstart + RMemSize;
1537
1538 if (((UDIUInt32)addr >= tstart) && ((UDIUInt32)addr < tend)) {
1539 return UDI29KIRAMSpace;
1540 } else if (((UDIUInt32)addr >= dstart) && ((UDIUInt32)addr < dend)) {
1541 return UDI29KDRAMSpace;
1542 } else if (((UDIUInt32)addr >= rstart) && ((UDIUInt32)addr < rend)) {
1543 /* FIXME: how do we determine between D_ROM and I_ROM */
1544 return UDI29KIROMSpace;
1545 } else /* FIXME: what do me do now? */
1546 return UDI29KDRAMSpace; /* Hmmm! */
1547}
1548/*********************************************************************** STUBS
1549*/
1550
1551void convert16() {;}
1552void convert32() {;}
199b2450 1553GDB_FILE * EchoFile = 0; /* used for debugging */
9bddba9a 1554int QuietMode = 0; /* used for debugging */
525390a2 1555\f
b58a1973
SG
1556#ifdef NO_HIF_SUPPORT
1557service_HIF(msg)
1558 union msg_t *msg;
1559{
1560 return(0); /* Emulate a failure */
1561}
1562#endif
1563\f
525390a2
JK
1564/* Target_ops vector. Not static because there does not seem to be
1565 any portable way to do a forward declaration of a static variable.
1566 The RS/6000 doesn't like "extern" followed by "static"; SunOS
1567 /bin/cc doesn't like "static" twice. */
9bddba9a 1568
525390a2 1569struct target_ops udi_ops = {
aa1dea48
SG
1570 "udi",
1571 "Remote UDI connected TIP",
a38b1233
JK
1572 "Remote debug an AMD 29k using UDI socket connection to TIP process.\n\
1573Arguments are\n\
1574`configuration-id AF_INET hostname port-number'\n\
1575 To connect via the network, where hostname and port-number specify the\n\
1576 host and port where you can connect via UDI.\n\
1577 configuration-id is unused.\n\
1578\n\
1579`configuration-id AF_UNIX socket-name tip-program'\n\
fe76016a 1580 To connect using a local connection to the \"tip.exe\" program which is\n\
a38b1233
JK
1581 supplied by AMD. If socket-name specifies an AF_UNIX socket then the\n\
1582 tip program must already be started; connect to it using that socket.\n\
1583 If not, start up tip-program, which should be the name of the tip\n\
1584 program. If appropriate, the PATH environment variable is searched.\n\
1585 configuration-id is unused.\n\
1586\n\
1587`configuration-id'\n\
1588 Look up the configuration in ./udi_soc or /etc/udi_soc, which\n\
1589 are files containing lines in the above formats. configuration-id is\n\
1590 used to pick which line of the file to use.",
aa1dea48
SG
1591 udi_open,
1592 udi_close,
1593 udi_attach,
1594 udi_detach,
1595 udi_resume,
1596 udi_wait,
1597 udi_fetch_registers,
1598 udi_store_registers,
a03d4f8e 1599 udi_prepare_to_store,
9bddba9a
SG
1600 udi_xfer_inferior_memory,
1601 udi_files_info,
aa1dea48
SG
1602 udi_insert_breakpoint,
1603 udi_remove_breakpoint,
1604 0, /* termial_init */
1605 0, /* terminal_inferior */
1606 0, /* terminal_ours_for_output */
1607 0, /* terminal_ours */
1608 0, /* terminal_info */
9bddba9a
SG
1609 udi_kill, /* FIXME, kill */
1610 udi_load,
1611 0, /* lookup_symbol */
aa1dea48
SG
1612 udi_create_inferior,
1613 udi_mourn, /* mourn_inferior FIXME */
5ee4e16c 1614 0, /* can_run */
3950a34e 1615 0, /* notice_signals */
aa1dea48
SG
1616 process_stratum,
1617 0, /* next */
1618 1, /* has_all_memory */
1619 1, /* has_memory */
1620 1, /* has_stack */
1621 1, /* has_registers */
1622 1, /* has_execution */
1623 0, /* sections */
1624 0, /* sections_end */
9bddba9a
SG
1625 OPS_MAGIC, /* Always the last thing */
1626};
1627
976bb0be
JK
1628void
1629_initialize_remote_udi ()
9bddba9a
SG
1630{
1631 add_target (&udi_ops);
1632}
This page took 0.329971 seconds and 4 git commands to generate.