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