1 /* Remote debugging interface for AMD 29k interfaced via UDI, for GDB.
2 Copyright 1990, 1992 Free Software Foundation, Inc.
3 Written by Daniel Mann. Contributed by AMD.
5 This file is part of GDB.
7 This program is free software; you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation; either version 2 of the License, or
10 (at your option) any later version.
12 This program is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 GNU General Public License for more details.
17 You should have received a copy of the GNU General Public License
18 along with this program; if not, write to the Free Software
19 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
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.
27 - Originally written by Daniel Mann at AMD for MiniMON and gdb 3.91.6.
28 - David Wood (wood@lab.ultra.nyu.edu) at New York University adapted this
29 file to gdb 3.95. I was unable to get this working on sun3os4
30 with termio, only with sgtty.
31 - Daniel Mann at AMD took the 3.95 adaptions above and replaced
32 MiniMON interface with UDI-p interface. */
45 #include "29k-share/udi/udiproc.h"
48 #include "gdbcore.h" /* For download function */
50 /* access the register store directly, without going through
51 the normal handler functions. This avoids an extra data copy. */
53 extern int stop_soon_quietly
; /* for wait_for_inferior */
54 extern struct value
*call_function_by_hand();
55 static void udi_resume
PARAMS ((int pid
, int step
, enum target_signal sig
));
56 static void udi_fetch_registers
PARAMS ((int regno
));
57 static void udi_load
PARAMS ((char *args
, int from_tty
));
58 static void fetch_register
PARAMS ((int regno
));
59 static void udi_store_registers
PARAMS ((int regno
));
60 static int store_register
PARAMS ((int regno
));
61 static int regnum_to_srnum
PARAMS ((int regno
));
62 static void udi_close
PARAMS ((int quitting
));
63 static CPUSpace udi_memory_space
PARAMS ((CORE_ADDR addr
));
64 static int udi_write_inferior_memory
PARAMS ((CORE_ADDR memaddr
, char *myaddr
,
66 static int udi_read_inferior_memory
PARAMS ((CORE_ADDR memaddr
, char *myaddr
,
68 static void download
PARAMS ((char *load_arg_string
, int from_tty
));
69 char CoffFileName
[100] = "";
71 #define FREEZE_MODE (read_register(CPS_REGNUM) & 0x400)
72 #define USE_SHADOW_PC ((processor_type == a29k_freeze_mode) && FREEZE_MODE)
74 static int timeout
= 5;
75 extern struct target_ops udi_ops
; /* Forward declaration */
77 /* Special register enumeration.
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
86 UDISessionId udi_session_id
= -1;
88 CPUOffset IMemStart
= 0;
89 CPUSizeT IMemSize
= 0;
90 CPUOffset DMemStart
= 0;
91 CPUSizeT DMemSize
= 0;
92 CPUOffset RMemStart
= 0;
93 CPUSizeT RMemSize
= 0;
97 UDIMemoryRange address_ranges
[2]; /* Text and data */
98 UDIResource entry
= {0, 0}; /* Entry point */
99 CPUSizeT stack_sizes
[2]; /* Regular and memory stacks */
101 #define SBUF_MAX 1024 /* maximum size of string handling buffer */
104 typedef struct bkpt_entry_str
109 unsigned int BreakId
;
111 #define BKPT_TABLE_SIZE 40
112 static bkpt_entry_t bkpt_table
[BKPT_TABLE_SIZE
];
113 extern char dfe_errmsg
[]; /* error string */
115 /* malloc'd name of the program on the remote system. */
116 static char *prog_name
= NULL
;
118 /* This is called not only when we first attach, but also when the
119 user types "run" after having attached. */
122 udi_create_inferior (execfile
, args
, env
)
131 if (prog_name
!= NULL
)
133 prog_name
= savestring (execfile
, strlen (execfile
));
135 else if (entry
.Offset
)
138 error ("No image loaded into target.");
140 if (udi_session_id
< 0)
142 printf_unfiltered("UDI connection not open yet.\n");
146 inferior_pid
= 40000;
149 download(execfile
, 0);
151 args1
= alloca (strlen(execfile
) + strlen(args
) + 2);
153 if (execfile
[0] == '\0')
155 /* It is empty. We need to quote it somehow, or else the target
156 will think there is no argument being passed here. According
157 to the UDI spec it is quoted "according to TIP OS rules" which
158 I guess means quoting it like the Unix shell should work
159 (sounds pretty bogus to me...). In fact it doesn't work (with
160 isstip anyway), but passing in two quotes as the argument seems
161 like a reasonable enough behavior anyway (I guess). */
163 strcpy (args1
, "''");
165 strcpy (args1
, execfile
);
167 strcat (args1
, args
);
169 UDIInitializeProcess (address_ranges
, /* ProcessMemory[] */
170 (UDIInt
)2, /* NumberOfRanges */
171 entry
, /* EntryPoint */
172 stack_sizes
, /* *StackSizes */
173 (UDIInt
)2, /* NumberOfStacks */
174 args1
); /* ArgString */
176 init_wait_for_inferior ();
177 clear_proceed_status ();
178 proceed (-1, TARGET_SIGNAL_DEFAULT
, 0);
185 /* Requiring "target udi" each time you run is a major pain. I suspect
186 this was just blindy copied from remote.c, in which "target" and
187 "run" are combined. Having a udi target without an inferior seems
188 to work between "target udi" and "run", so why not now? */
189 pop_target (); /* Pop back to no-child state */
191 /* But if we're going to want to run it again, we better remove the
193 remove_breakpoints ();
194 generic_mourn_inferior ();
197 /******************************************************************** UDI_OPEN
198 ** Open a connection to remote TIP.
199 NAME is the socket domain used for communication with the TIP,
200 then a space and the socket name or TIP-host name.
201 '<udi_udi_config_id>' for example.
204 /* XXX - need cleanups for udiconnect for various failures!!! */
206 static char *udi_config_id
;
208 udi_open (name
, from_tty
)
215 UDIMemoryRange KnownMemory
[10];
216 UDIUInt32 ChipVersions
[10];
217 UDIInt NumberOfRanges
= 10;
218 UDIInt NumberOfChips
= 10;
220 UDIUInt32 TIPId
, TargetId
, DFEId
, DFE
, TIP
, DFEIPCId
, TIPIPCId
;
222 target_preopen(from_tty
);
226 for (cnt
= 0; cnt
< BKPT_TABLE_SIZE
; cnt
++)
227 bkpt_table
[cnt
].Type
= 0;
230 free (udi_config_id
);
233 error("Usage: target udi config_id, where config_id appears in udi_soc file");
235 udi_config_id
= strdup (strtok (name
, " \t"));
237 if (UDIConnect (udi_config_id
, &udi_session_id
))
238 error("UDIConnect() failed: %s\n", dfe_errmsg
);
240 push_target (&udi_ops
);
243 ** Initialize target configuration structure (global)
245 if (UDIGetTargetConfig (KnownMemory
, &NumberOfRanges
,
246 ChipVersions
, &NumberOfChips
))
247 error ("UDIGetTargetConfig() failed");
248 if (NumberOfChips
> 2)
249 fprintf_unfiltered(gdb_stderr
,"Target has more than one processor\n");
250 for (cnt
=0; cnt
< NumberOfRanges
; cnt
++)
252 switch(KnownMemory
[cnt
].Space
)
255 fprintf_unfiltered(gdb_stderr
, "UDIGetTargetConfig() unknown memory space\n");
259 case UDI29KIROMSpace
:
260 RMemStart
= KnownMemory
[cnt
].Offset
;
261 RMemSize
= KnownMemory
[cnt
].Size
;
263 case UDI29KIRAMSpace
:
264 IMemStart
= KnownMemory
[cnt
].Offset
;
265 IMemSize
= KnownMemory
[cnt
].Size
;
267 case UDI29KDRAMSpace
:
268 DMemStart
= KnownMemory
[cnt
].Offset
;
269 DMemSize
= KnownMemory
[cnt
].Size
;
274 a29k_get_processor_type ();
276 if (UDICreateProcess (&PId
))
277 fprintf_unfiltered(gdb_stderr
, "UDICreateProcess() failed\n");
279 /* Print out some stuff, letting the user now what's going on */
280 if (UDICapabilities (&TIPId
, &TargetId
, DFEId
, DFE
, &TIP
, &DFEIPCId
,
282 error ("UDICapabilities() failed");
285 printf_filtered ("Connected via UDI socket,\n\
286 DFE-IPC version %x.%x.%x TIP-IPC version %x.%x.%x TIP version %x.%x.%x\n %s\n",
287 (DFEIPCId
>>8)&0xf, (DFEIPCId
>>4)&0xf, DFEIPCId
&0xf,
288 (TIPIPCId
>>8)&0xf, (TIPIPCId
>>4)&0xf, TIPIPCId
&0xf,
289 (TargetId
>>8)&0xf, (TargetId
>>4)&0xf, TargetId
&0xf,
294 /******************************************************************* UDI_CLOSE
295 Close the open connection to the TIP process.
296 Use this when you want to detach and do something else
299 udi_close (quitting
) /*FIXME: how is quitting used */
302 if (udi_session_id
< 0)
305 /* We should never get here if there isn't something valid in
308 if (UDIDisconnect (udi_session_id
, UDITerminateSession
))
311 warning ("UDIDisconnect() failed in udi_close");
313 error ("UDIDisconnect() failed in udi_close");
316 /* Do not try to close udi_session_id again, later in the program. */
320 printf_filtered (" Ending remote debugging\n");
323 /**************************************************************** UDI_ATACH */
324 /* Attach to a program that is already loaded and running
325 * Upon exiting the process's execution is stopped.
328 udi_attach (args
, from_tty
)
337 UDIBool HostEndian
= 0;
341 error_no_arg ("program to attach");
343 if (udi_session_id
< 0)
344 error ("UDI connection not opened yet, use the 'target udi' command.\n");
347 printf_unfiltered ("Attaching to remote program %s...\n", prog_name
);
350 From
.Space
= UDI29KSpecialRegs
;
352 if (err
= UDIRead(From
, &PC_adds
, Count
, Size
, &CountDone
, HostEndian
))
353 error ("UDIRead failed in udi_attach");
354 printf_unfiltered ("Remote process is now halted, pc1 = 0x%x.\n", PC_adds
);
356 /************************************************************* UDI_DETACH */
357 /* Terminate the open connection to the TIP process.
358 Use this when you want to detach and do something else
359 with your gdb. Leave remote process running (with no breakpoints set). */
361 udi_detach (args
,from_tty
)
366 remove_breakpoints(); /* Just in case there were any left in */
368 if (UDIDisconnect (udi_session_id
, UDIContinueSession
))
369 error ("UDIDisconnect() failed in udi_detach");
371 /* calls udi_close to do the real work (which looks like it calls
372 UDIDisconnect with UDITerminateSession, FIXME). */
375 /* FIXME, message too similar to what udi_close prints. */
377 printf_unfiltered ("Ending remote debugging\n");
381 /****************************************************************** UDI_RESUME
382 ** Tell the remote machine to resume. */
385 udi_resume (pid
, step
, sig
)
387 enum target_signal sig
;
391 UDIStepType StepType
= UDIStepNatural
;
394 if (step
) /* step 1 instruction */
396 tip_error
= UDIStep (Steps
, StepType
, Range
);
400 fprintf_unfiltered (gdb_stderr
, "UDIStep() error = %d\n", tip_error
);
401 error ("failed in udi_resume");
405 error ("UDIExecute() failed in udi_resume");
408 /******************************************************************** UDI_WAIT
409 ** Wait until the remote machine stops, then return,
410 storing status in STATUS just as `wait' would. */
413 udi_wait (pid
, status
)
415 struct target_waitstatus
*status
;
421 int old_timeout
= timeout
;
422 int old_immediate_quit
= immediate_quit
;
425 status
->kind
= TARGET_WAITKIND_EXITED
;
426 status
->value
.integer
= 0;
428 /* wait for message to arrive. It should be:
429 If the target stops executing, udi_wait() should return.
431 timeout
= 0; /* Wait indefinetly for a message */
432 immediate_quit
= 1; /* Helps ability to QUIT */
437 MaxTime
= UDIWaitForever
;
438 UDIWait(MaxTime
, &PId
, &StopReason
);
439 QUIT
; /* Let user quit if they want */
441 switch (StopReason
& UDIGrossState
)
444 if (UDIGetStdout (sbuf
, (UDISizeT
)SBUF_MAX
, &CountDone
))
445 /* This is said to happen if the program tries to output
446 a whole bunch of output (more than SBUF_MAX, I would
447 guess). It doesn't seem to happen with the simulator. */
448 warning ("UDIGetStdout() failed in udi_wait");
449 fwrite (sbuf
, 1, CountDone
, gdb_stdout
);
450 gdb_flush(gdb_stdout
);
454 UDIGetStderr (sbuf
, (UDISizeT
)SBUF_MAX
, &CountDone
);
455 fwrite (sbuf
, 1, CountDone
, gdb_stderr
);
456 gdb_flush(gdb_stderr
);
469 } while (i
< SBUF_MAX
&& ch
!= '\n');
470 UDIPutStdin (sbuf
, (UDISizeT
)i
, &CountDone
);
475 /* In spite of the fact that we told UDIWait to wait forever, it will
476 return spuriously sometimes. */
485 switch (StopReason
& UDIGrossState
)
488 printf_unfiltered("Am290*0 received vector number %d\n", StopReason
>> 24);
490 switch (StopReason
>> 8)
492 case 0: /* Illegal opcode */
493 printf_unfiltered(" (break point)\n");
494 status
->kind
= TARGET_WAITKIND_STOPPED
;
495 status
->value
.sig
= TARGET_SIGNAL_TRAP
;
497 case 1: /* Unaligned Access */
498 status
->kind
= TARGET_WAITKIND_STOPPED
;
499 status
->value
.sig
= TARGET_SIGNAL_BUS
;
503 status
->kind
= TARGET_WAITKIND_STOPPED
;
504 status
->value
.sig
= TARGET_SIGNAL_FPE
;
506 case 5: /* Protection Violation */
507 status
->kind
= TARGET_WAITKIND_STOPPED
;
508 /* Why not SEGV? What is a Protection Violation? */
509 status
->value
.sig
= TARGET_SIGNAL_ILL
;
513 case 8: /* User Instruction Mapping Miss */
514 case 9: /* User Data Mapping Miss */
515 case 10: /* Supervisor Instruction Mapping Miss */
516 case 11: /* Supervisor Data Mapping Miss */
517 status
->kind
= TARGET_WAITKIND_STOPPED
;
518 status
->value
.sig
= TARGET_SIGNAL_SEGV
;
522 status
->kind
= TARGET_WAITKIND_STOPPED
;
523 status
->value
.sig
= TARGET_SIGNAL_ILL
;
526 status
->kind
= TARGET_WAITKIND_STOPPED
;
527 status
->value
.sig
= TARGET_SIGNAL_ALRM
;
530 status
->kind
= TARGET_WAITKIND_STOPPED
;
531 status
->value
.sig
= TARGET_SIGNAL_TRAP
;
536 case 19: /* INTR3/Internal */
539 status
->kind
= TARGET_WAITKIND_STOPPED
;
540 status
->value
.sig
= TARGET_SIGNAL_INT
;
542 case 22: /* Floating-Point Exception */
543 status
->kind
= TARGET_WAITKIND_STOPPED
;
545 status
->value
.sig
= TARGET_SIGNAL_ILL
;
547 case 77: /* assert 77 */
548 status
->kind
= TARGET_WAITKIND_STOPPED
;
549 status
->value
.sig
= TARGET_SIGNAL_TRAP
;
552 status
->kind
= TARGET_WAITKIND_EXITED
;
553 status
->value
.integer
= 0;
556 case UDINotExecuting
:
557 status
->kind
= TARGET_WAITKIND_STOPPED
;
558 status
->value
.sig
= TARGET_SIGNAL_TERM
;
561 status
->kind
= TARGET_WAITKIND_STOPPED
;
562 status
->value
.sig
= TARGET_SIGNAL_TSTP
;
565 status
->kind
= TARGET_WAITKIND_STOPPED
;
566 status
->value
.sig
= TARGET_SIGNAL_URG
;
570 status
->kind
= TARGET_WAITKIND_STOPPED
;
571 status
->value
.sig
= TARGET_SIGNAL_TRAP
;
574 status
->kind
= TARGET_WAITKIND_STOPPED
;
575 status
->value
.sig
= TARGET_SIGNAL_STOP
;
578 status
->kind
= TARGET_WAITKIND_STOPPED
;
579 status
->value
.sig
= TARGET_SIGNAL_KILL
;
583 status
->kind
= TARGET_WAITKIND_EXITED
;
584 status
->value
.integer
= 0;
587 timeout
= old_timeout
; /* Restore original timeout value */
588 immediate_quit
= old_immediate_quit
;
593 /* Handy for debugging */
601 UDIBool HostEndian
= 0;
604 unsigned long myregs
[256];
607 From
.Space
= UDI29KPC
;
609 To
= (UDIUInt32
*)pc
;
612 err
= UDIRead(From
, To
, Count
, Size
, &CountDone
, HostEndian
);
614 printf_unfiltered ("err = %d, CountDone = %d, pc[0] = 0x%x, pc[1] = 0x%x\n",
615 err
, CountDone
, pc
[0], pc
[1]);
617 udi_fetch_registers(-1);
619 printf_unfiltered("other pc1 = 0x%x, pc0 = 0x%x\n", *(int *)®isters
[4 * PC_REGNUM
],
620 *(int *)®isters
[4 * NPC_REGNUM
]);
622 /* Now, read all the registers globally */
624 From
.Space
= UDI29KGlobalRegs
;
626 err
= UDIRead(From
, myregs
, 256, 4, &CountDone
, HostEndian
);
628 printf ("err = %d, CountDone = %d\n", err
, CountDone
);
632 for (i
= 0; i
< 256; i
+= 2)
633 printf("%d:\t%#10x\t%11d\t%#10x\t%11d\n", i
, myregs
[i
], myregs
[i
],
634 myregs
[i
+1], myregs
[i
+1]);
641 /********************************************************** UDI_FETCH_REGISTERS
642 * Read a remote register 'regno'.
643 * If regno==-1 then read all the registers.
646 udi_fetch_registers (regno
)
654 UDIBool HostEndian
= 0;
659 fetch_register(regno
);
665 From
.Space
= UDI29KGlobalRegs
;
667 To
= (UDIUInt32
*)®isters
[4 * GR1_REGNUM
];
669 if (err
= UDIRead(From
, To
, Count
, Size
, &CountDone
, HostEndian
))
670 error("UDIRead() failed in udi_fetch_registers");
672 register_valid
[GR1_REGNUM
] = 1;
674 #if defined(GR64_REGNUM) /* Read gr64-127 */
676 /* Global Registers gr64-gr95 */
678 From
.Space
= UDI29KGlobalRegs
;
680 To
= (UDIUInt32
*)®isters
[4 * GR64_REGNUM
];
682 if (err
= UDIRead(From
, To
, Count
, Size
, &CountDone
, HostEndian
))
683 error("UDIRead() failed in udi_fetch_registers");
685 for (i
= GR64_REGNUM
; i
< GR64_REGNUM
+ 32; i
++)
686 register_valid
[i
] = 1;
688 #endif /* GR64_REGNUM */
690 /* Global Registers gr96-gr127 */
692 From
.Space
= UDI29KGlobalRegs
;
694 To
= (UDIUInt32
*)®isters
[4 * GR96_REGNUM
];
696 if (err
= UDIRead(From
, To
, Count
, Size
, &CountDone
, HostEndian
))
697 error("UDIRead() failed in udi_fetch_registers");
699 for (i
= GR96_REGNUM
; i
< GR96_REGNUM
+ 32; i
++)
700 register_valid
[i
] = 1;
702 /* Local Registers */
704 From
.Space
= UDI29KLocalRegs
;
706 To
= (UDIUInt32
*)®isters
[4 * LR0_REGNUM
];
708 if (err
= UDIRead(From
, To
, Count
, Size
, &CountDone
, HostEndian
))
709 error("UDIRead() failed in udi_fetch_registers");
711 for (i
= LR0_REGNUM
; i
< LR0_REGNUM
+ 128; i
++)
712 register_valid
[i
] = 1;
714 /* Protected Special Registers */
716 From
.Space
= UDI29KSpecialRegs
;
718 To
= (UDIUInt32
*)®isters
[4 * SR_REGNUM(0)];
720 if (err
= UDIRead(From
, To
, Count
, Size
, &CountDone
, HostEndian
))
721 error("UDIRead() failed in udi_fetch_registers");
723 for (i
= SR_REGNUM(0); i
< SR_REGNUM(0) + 15; i
++)
724 register_valid
[i
] = 1;
726 if (USE_SHADOW_PC
) { /* Let regno_to_srnum() handle the register number */
727 fetch_register(NPC_REGNUM
);
728 fetch_register(PC_REGNUM
);
729 fetch_register(PC2_REGNUM
);
731 /* Unprotected Special Registers sr128-sr135 */
733 From
.Space
= UDI29KSpecialRegs
;
735 To
= (UDIUInt32
*)®isters
[4 * SR_REGNUM(128)];
737 if (err
= UDIRead(From
, To
, Count
, Size
, &CountDone
, HostEndian
))
738 error("UDIRead() failed in udi_fetch_registers");
740 for (i
= SR_REGNUM(128); i
< SR_REGNUM(128) + 135-128+1; i
++)
741 register_valid
[i
] = 1;
746 printf_unfiltered("Fetching all registers\n");
747 printf_unfiltered("Fetching PC0 = 0x%x, PC1 = 0x%x, PC2 = 0x%x\n",
748 read_register(NPC_REGNUM
), read_register(PC_REGNUM
),
749 read_register(PC2_REGNUM
));
752 /* There doesn't seem to be any way to get these. */
755 supply_register (FPE_REGNUM
, (char *) &val
);
756 supply_register (INTE_REGNUM
, (char *) &val
);
757 supply_register (FPS_REGNUM
, (char *) &val
);
758 supply_register (EXO_REGNUM
, (char *) &val
);
763 /********************************************************* UDI_STORE_REGISTERS
764 ** Store register regno into the target.
765 * If regno==-1 then store all the registers.
769 udi_store_registers (regno
)
777 UDIBool HostEndian
= 0;
781 store_register(regno
);
787 printf_unfiltered("Storing all registers\n");
788 printf_unfiltered("PC0 = 0x%x, PC1 = 0x%x, PC2 = 0x%x\n", read_register(NPC_REGNUM
),
789 read_register(PC_REGNUM
), read_register(PC2_REGNUM
));
794 From
= (UDIUInt32
*)®isters
[4 * GR1_REGNUM
];
795 To
.Space
= UDI29KGlobalRegs
;
798 if(UDIWrite(From
, To
, Count
, Size
, &CountDone
, HostEndian
))
799 error("UDIWrite() failed in udi_store_regisetrs");
801 #if defined(GR64_REGNUM)
803 /* Global registers gr64-gr95 */
805 From
= (UDIUInt32
*)®isters
[4 * GR64_REGNUM
];
806 To
.Space
= UDI29KGlobalRegs
;
809 if(UDIWrite(From
, To
, Count
, Size
, &CountDone
, HostEndian
))
810 error("UDIWrite() failed in udi_store_regisetrs");
812 #endif /* GR64_REGNUM */
814 /* Global registers gr96-gr127 */
816 From
= (UDIUInt32
*)®isters
[4 * GR96_REGNUM
];
817 To
.Space
= UDI29KGlobalRegs
;
820 if(UDIWrite(From
, To
, Count
, Size
, &CountDone
, HostEndian
))
821 error("UDIWrite() failed in udi_store_regisetrs");
823 /* Local Registers */
825 From
= (UDIUInt32
*)®isters
[4 * LR0_REGNUM
];
826 To
.Space
= UDI29KLocalRegs
;
829 if(UDIWrite(From
, To
, Count
, Size
, &CountDone
, HostEndian
))
830 error("UDIWrite() failed in udi_store_regisetrs");
833 /* Protected Special Registers */ /* VAB through TMR */
835 From
= (UDIUInt32
*)®isters
[4 * SR_REGNUM(0)];
836 To
.Space
= UDI29KSpecialRegs
;
839 if(UDIWrite(From
, To
, Count
, Size
, &CountDone
, HostEndian
))
840 error("UDIWrite() failed in udi_store_regisetrs");
842 /* PC0, PC1, PC2 possibly as shadow registers */
844 From
= (UDIUInt32
*)®isters
[4 * SR_REGNUM(10)];
845 To
.Space
= UDI29KSpecialRegs
;
848 To
.Offset
= 20; /* SPC0 */
850 To
.Offset
= 10; /* PC0 */
851 if(UDIWrite(From
, To
, Count
, Size
, &CountDone
, HostEndian
))
852 error("UDIWrite() failed in udi_store_regisetrs");
854 /* PC1 via UDI29KPC */
856 From
= (UDIUInt32
*)®isters
[4 * PC_REGNUM
];
858 To
.Offset
= 0; /* PC1 */
860 if (UDIWrite (From
, To
, Count
, Size
, &CountDone
, HostEndian
))
861 error ("UDIWrite() failed in udi_store_regisetrs");
865 From
= (UDIUInt32
*)®isters
[4 * SR_REGNUM(13)];
866 To
.Space
= UDI29KSpecialRegs
;
869 if(UDIWrite(From
, To
, Count
, Size
, &CountDone
, HostEndian
))
870 error("UDIWrite() failed in udi_store_regisetrs");
872 /* Unprotected Special Registers */
874 From
= (UDIUInt32
*)®isters
[4 * SR_REGNUM(128)];
875 To
.Space
= UDI29KSpecialRegs
;
878 if(UDIWrite(From
, To
, Count
, Size
, &CountDone
, HostEndian
))
879 error("UDIWrite() failed in udi_store_regisetrs");
881 registers_changed ();
884 /****************************************************** UDI_PREPARE_TO_STORE */
885 /* Get ready to modify the registers array. On machines which store
886 individual registers, this doesn't need to do anything. On machines
887 which store all the registers in one fell swoop, this makes sure
888 that registers contains all the registers from the program being
892 udi_prepare_to_store ()
894 /* Do nothing, since we can store individual regs */
897 /********************************************************** TRANSLATE_ADDR */
902 #if defined(ULTRA3) && defined(KERNEL_DEBUGGING)
903 /* Check for a virtual address in the kernel */
904 /* Assume physical address of ublock is in paddr_u register */
905 /* FIXME: doesn't work for user virtual addresses */
906 if (addr
>= UVADDR
) {
907 /* PADDR_U register holds the physical address of the ublock */
908 CORE_ADDR i
= (CORE_ADDR
)read_register(PADDR_U_REGNUM
);
909 return(i
+ addr
- (CORE_ADDR
)UVADDR
);
917 /************************************************* UDI_XFER_INFERIOR_MEMORY */
918 /* FIXME! Merge these two. */
920 udi_xfer_inferior_memory (memaddr
, myaddr
, len
, write
)
927 memaddr
= translate_addr(memaddr
);
930 return udi_write_inferior_memory (memaddr
, myaddr
, len
);
932 return udi_read_inferior_memory (memaddr
, myaddr
, len
);
935 /********************************************************** UDI_FILES_INFO */
939 printf_unfiltered ("\tAttached to UDI socket to %s and running program %s.\n",
940 udi_config_id
, prog_name
);
943 /**************************************************** UDI_INSERT_BREAKPOINT */
945 udi_insert_breakpoint (addr
, contents_cache
)
947 char *contents_cache
;
952 for (cnt
= 0; cnt
< BKPT_TABLE_SIZE
; cnt
++)
953 if (bkpt_table
[cnt
].Type
== 0) /* Find first free slot */
956 if(cnt
>= BKPT_TABLE_SIZE
)
957 error("Too many breakpoints set");
959 bkpt_table
[cnt
].Addr
.Offset
= addr
;
960 bkpt_table
[cnt
].Addr
.Space
= UDI29KIRAMSpace
;
961 bkpt_table
[cnt
].PassCount
= 1;
962 bkpt_table
[cnt
].Type
= UDIBreakFlagExecute
;
964 err
= UDISetBreakpoint(bkpt_table
[cnt
].Addr
,
965 bkpt_table
[cnt
].PassCount
,
966 bkpt_table
[cnt
].Type
,
967 &bkpt_table
[cnt
].BreakId
);
969 if (err
== 0) return 0; /* Success */
971 bkpt_table
[cnt
].Type
= 0;
972 error("UDISetBreakpoint returned error code %d\n", err
);
975 /**************************************************** UDI_REMOVE_BREAKPOINT */
977 udi_remove_breakpoint (addr
, contents_cache
)
979 char *contents_cache
;
984 for (cnt
= 0; cnt
< BKPT_TABLE_SIZE
; cnt
++)
985 if (bkpt_table
[cnt
].Addr
.Offset
== addr
) /* Find matching breakpoint */
988 if(cnt
>= BKPT_TABLE_SIZE
)
989 error("Can't find breakpoint in table");
991 bkpt_table
[cnt
].Type
= 0;
993 err
= UDIClearBreakpoint(bkpt_table
[cnt
].BreakId
);
994 if (err
== 0) return 0; /* Success */
996 error("UDIClearBreakpoint returned error code %d\n", err
);
1000 udi_kill(arg
,from_tty
)
1007 UDIStop does not really work as advertised. It causes the TIP to close it's
1008 connection, which usually results in GDB dying with a SIGPIPE. For now, we
1009 just invoke udi_close, which seems to get things right.
1013 udi_session_id
= -1;
1017 printf_unfiltered("Target has been stopped.");
1024 /* Keep the target around, e.g. so "run" can do the right thing when
1025 we are already debugging something. FIXME-maybe: should we kill the
1026 TIP with UDIDisconnect using UDITerminateSession, and then restart
1027 it on the next "run"? */
1033 Load a program into the target. Args are: `program {options}'. The options
1034 are used to control loading of the program, and are NOT passed onto the
1035 loaded code as arguments. (You need to use the `run' command to do that.)
1038 -ms %d Set mem stack size to %d
1039 -rs %d Set regular stack size to %d
1040 -i send init info (default)
1041 -noi don't send init info
1042 -[tT] Load Text section
1043 -[dD] Load Data section
1044 -[bB] Load BSS section
1045 -[lL] Load Lit section
1049 download(load_arg_string
, from_tty
)
1050 char *load_arg_string
;
1053 #define DEFAULT_MEM_STACK_SIZE 0x6000
1054 #define DEFAULT_REG_STACK_SIZE 0x2000
1061 int load_text
= 1, load_data
= 1, load_bss
= 1, load_lit
= 1;
1063 address_ranges
[0].Space
= UDI29KIRAMSpace
;
1064 address_ranges
[0].Offset
= 0xffffffff;
1065 address_ranges
[0].Size
= 0;
1067 address_ranges
[1].Space
= UDI29KDRAMSpace
;
1068 address_ranges
[1].Offset
= 0xffffffff;
1069 address_ranges
[1].Size
= 0;
1071 stack_sizes
[0] = DEFAULT_REG_STACK_SIZE
;
1072 stack_sizes
[1] = DEFAULT_MEM_STACK_SIZE
;
1076 filename
= strtok(load_arg_string
, " \t");
1078 error ("Must specify at least a file name with the load command");
1080 filename
= tilde_expand (filename
);
1081 make_cleanup (free
, filename
);
1083 while (token
= strtok (NULL
, " \t"))
1085 if (token
[0] == '-')
1089 if (STREQ (token
, "ms"))
1090 stack_sizes
[1] = atol (strtok (NULL
, " \t"));
1091 else if (STREQ (token
, "rs"))
1092 stack_sizes
[0] = atol (strtok (NULL
, " \t"));
1095 load_text
= load_data
= load_bss
= load_lit
= 0;
1118 error ("Unknown UDI load option -%s", token
-1);
1125 pbfd
= bfd_openr (filename
, gnutarget
);
1128 perror_with_name (filename
);
1130 make_cleanup (bfd_close
, pbfd
);
1135 if (!bfd_check_format (pbfd
, bfd_object
))
1136 error ("It doesn't seem to be an object file");
1138 for (section
= pbfd
->sections
; section
; section
= section
->next
)
1140 if (bfd_get_section_flags (pbfd
, section
) & SEC_ALLOC
)
1144 unsigned long section_size
, section_end
;
1145 const char *section_name
;
1147 section_name
= bfd_get_section_name (pbfd
, section
);
1148 if (STREQ (section_name
, ".text") && !load_text
)
1150 else if (STREQ (section_name
, ".data") && !load_data
)
1152 else if (STREQ (section_name
, ".bss") && !load_bss
)
1154 else if (STREQ (section_name
, ".lit") && !load_lit
)
1157 To
.Offset
= bfd_get_section_vma (pbfd
, section
);
1158 section_size
= bfd_section_size (pbfd
, section
);
1159 section_end
= To
.Offset
+ section_size
;
1161 if (section_size
== 0)
1162 /* This is needed at least in the BSS case, where the code
1163 below starts writing before it even checks the size. */
1166 printf_unfiltered("[Loading section %s at %x (%d bytes)]\n",
1171 if (bfd_get_section_flags (pbfd
, section
) & SEC_CODE
)
1173 To
.Space
= UDI29KIRAMSpace
;
1175 address_ranges
[0].Offset
= min (address_ranges
[0].Offset
,
1177 address_ranges
[0].Size
= max (address_ranges
[0].Size
,
1179 - address_ranges
[0].Offset
);
1183 To
.Space
= UDI29KDRAMSpace
;
1185 address_ranges
[1].Offset
= min (address_ranges
[1].Offset
,
1187 address_ranges
[1].Size
= max (address_ranges
[1].Size
,
1189 - address_ranges
[1].Offset
);
1192 if (bfd_get_section_flags (pbfd
, section
) & SEC_LOAD
) /* Text, data or lit */
1198 while (section_size
> 0)
1202 Count
= min (section_size
, 1024);
1204 bfd_get_section_contents (pbfd
, section
, buffer
, fptr
,
1207 err
= UDIWrite ((UDIHostMemPtr
)buffer
, /* From */
1210 (UDISizeT
)1, /* Size */
1211 &Count
, /* CountDone */
1212 (UDIBool
)0); /* HostEndian */
1214 error ("UDIWrite failed, error = %d", err
);
1218 section_size
-= Count
;
1224 unsigned long zero
= 0;
1226 /* Write a zero byte at the vma */
1227 /* FIXME: Broken for sections of 1-3 bytes (we test for
1229 err
= UDIWrite ((UDIHostMemPtr
)&zero
, /* From */
1231 (UDICount
)1, /* Count */
1232 (UDISizeT
)4, /* Size */
1233 &Count
, /* CountDone */
1234 (UDIBool
)0); /* HostEndian */
1236 error ("UDIWrite failed, error = %d", err
);
1241 /* Now, duplicate it for the length of the BSS */
1242 err
= UDICopy (From
, /* From */
1244 (UDICount
)(section_size
/4 - 1), /* Count */
1245 (UDISizeT
)4, /* Size */
1246 &Count
, /* CountDone */
1247 (UDIBool
)1); /* Direction */
1253 xerr
= UDIGetErrorMsg(err
, 100, message
, &Count
);
1255 fprintf_unfiltered (gdb_stderr
, "Error is %s\n", message
);
1257 fprintf_unfiltered (gdb_stderr
, "xerr is %d\n", xerr
);
1258 error ("UDICopy failed, error = %d", err
);
1265 entry
.Space
= UDI29KIRAMSpace
;
1266 entry
.Offset
= bfd_get_start_address (pbfd
);
1271 /* User interface to download an image into the remote target. See download()
1272 * for details on args.
1276 udi_load(args
, from_tty
)
1280 download (args
, from_tty
);
1282 symbol_file_add (strtok (args
, " \t"), from_tty
, 0, 0, 0, 0);
1285 /*************************************************** UDI_WRITE_INFERIOR_MEMORY
1286 ** Copy LEN bytes of data from debugger memory at MYADDR
1287 to inferior's memory at MEMADDR. Returns number of bytes written. */
1289 udi_write_inferior_memory (memaddr
, myaddr
, len
)
1299 UDICount CountDone
= 0;
1300 UDIBool HostEndian
= 0;
1302 To
.Space
= udi_memory_space(memaddr
);
1303 From
= (UDIUInt32
*)myaddr
;
1305 while (nwritten
< len
)
1306 { Count
= len
- nwritten
;
1307 if (Count
> MAXDATA
) Count
= MAXDATA
;
1308 To
.Offset
= memaddr
+ nwritten
;
1309 if(UDIWrite(From
, To
, Count
, Size
, &CountDone
, HostEndian
))
1310 { error("UDIWrite() failed in udi_write_inferrior_memory");
1314 { nwritten
+= CountDone
;
1321 /**************************************************** UDI_READ_INFERIOR_MEMORY
1322 ** Read LEN bytes from inferior memory at MEMADDR. Put the result
1323 at debugger address MYADDR. Returns number of bytes read. */
1325 udi_read_inferior_memory(memaddr
, myaddr
, len
)
1335 UDICount CountDone
= 0;
1336 UDIBool HostEndian
= 0;
1339 From
.Space
= udi_memory_space(memaddr
);
1340 To
= (UDIUInt32
*)myaddr
;
1343 { Count
= len
- nread
;
1344 if (Count
> MAXDATA
) Count
= MAXDATA
;
1345 From
.Offset
= memaddr
+ nread
;
1346 if(err
= UDIRead(From
, To
, Count
, Size
, &CountDone
, HostEndian
))
1347 { error("UDIRead() failed in udi_read_inferrior_memory");
1351 { nread
+= CountDone
;
1358 /********************************************************************* WARNING
1363 error ("ERROR while loading program into remote TIP: $d\n", num
);
1367 /*****************************************************************************/
1368 /* Fetch a single register indicatated by 'regno'.
1369 * Returns 0/-1 on success/failure.
1372 fetch_register (regno
)
1380 UDIBool HostEndian
= 0;
1384 if (regno
== GR1_REGNUM
)
1386 From
.Space
= UDI29KGlobalRegs
;
1389 else if (regno
>= GR96_REGNUM
&& regno
< GR96_REGNUM
+ 32)
1391 From
.Space
= UDI29KGlobalRegs
;
1392 From
.Offset
= (regno
- GR96_REGNUM
) + 96;;
1395 #if defined(GR64_REGNUM)
1397 else if (regno
>= GR64_REGNUM
&& regno
< GR64_REGNUM
+ 32 )
1399 From
.Space
= UDI29KGlobalRegs
;
1400 From
.Offset
= (regno
- GR64_REGNUM
) + 64;
1403 #endif /* GR64_REGNUM */
1405 else if (regno
>= LR0_REGNUM
&& regno
< LR0_REGNUM
+ 128)
1407 From
.Space
= UDI29KLocalRegs
;
1408 From
.Offset
= (regno
- LR0_REGNUM
);
1410 else if (regno
>=FPE_REGNUM
&& regno
<=EXO_REGNUM
)
1413 supply_register(160 + (regno
- FPE_REGNUM
),(char *) &val
);
1414 return; /* Pretend Success */
1418 From
.Space
= UDI29KSpecialRegs
;
1419 From
.Offset
= regnum_to_srnum(regno
);
1422 if (err
= UDIRead(From
, &To
, Count
, Size
, &CountDone
, HostEndian
))
1423 error("UDIRead() failed in udi_fetch_registers");
1425 supply_register(regno
, (char *) &To
);
1428 printf_unfiltered("Fetching register %s = 0x%x\n", reg_names
[regno
], To
);
1430 /*****************************************************************************/
1431 /* Store a single register indicated by 'regno'.
1432 * Returns 0/-1 on success/failure.
1435 store_register (regno
)
1444 UDIBool HostEndian
= 0;
1446 From
= read_register (regno
); /* get data value */
1449 printf_unfiltered("Storing register %s = 0x%x\n", reg_names
[regno
], From
);
1451 if (regno
== GR1_REGNUM
)
1453 To
.Space
= UDI29KGlobalRegs
;
1455 result
= UDIWrite(&From
, To
, Count
, Size
, &CountDone
, HostEndian
);
1456 /* Setting GR1 changes the numbers of all the locals, so invalidate the
1457 * register cache. Do this *after* calling read_register, because we want
1458 * read_register to return the value that write_register has just stuffed
1459 * into the registers array, not the value of the register fetched from
1462 registers_changed ();
1464 #if defined(GR64_REGNUM)
1465 else if (regno
>= GR64_REGNUM
&& regno
< GR64_REGNUM
+ 32 )
1467 To
.Space
= UDI29KGlobalRegs
;
1468 To
.Offset
= (regno
- GR64_REGNUM
) + 64;
1469 result
= UDIWrite(&From
, To
, Count
, Size
, &CountDone
, HostEndian
);
1471 #endif /* GR64_REGNUM */
1472 else if (regno
>= GR96_REGNUM
&& regno
< GR96_REGNUM
+ 32)
1474 To
.Space
= UDI29KGlobalRegs
;
1475 To
.Offset
= (regno
- GR96_REGNUM
) + 96;
1476 result
= UDIWrite(&From
, To
, Count
, Size
, &CountDone
, HostEndian
);
1478 else if (regno
>= LR0_REGNUM
&& regno
< LR0_REGNUM
+ 128)
1480 To
.Space
= UDI29KLocalRegs
;
1481 To
.Offset
= (regno
- LR0_REGNUM
);
1482 result
= UDIWrite(&From
, To
, Count
, Size
, &CountDone
, HostEndian
);
1484 else if (regno
>= FPE_REGNUM
&& regno
<= EXO_REGNUM
)
1485 return 0; /* Pretend Success */
1486 else if (regno
== PC_REGNUM
)
1488 /* PC1 via UDI29KPC */
1490 To
.Space
= UDI29KPC
;
1491 To
.Offset
= 0; /* PC1 */
1492 result
= UDIWrite (&From
, To
, Count
, Size
, &CountDone
, HostEndian
);
1494 /* Writing to this loc actually changes the values of pc0 & pc1 */
1496 register_valid
[PC_REGNUM
] = 0; /* pc1 */
1497 register_valid
[NPC_REGNUM
] = 0; /* pc0 */
1499 else /* An unprotected or protected special register */
1501 To
.Space
= UDI29KSpecialRegs
;
1502 To
.Offset
= regnum_to_srnum(regno
);
1503 result
= UDIWrite(&From
, To
, Count
, Size
, &CountDone
, HostEndian
);
1507 error("UDIWrite() failed in store_registers");
1511 /********************************************************** REGNUM_TO_SRNUM */
1513 * Convert a gdb special register number to a 29000 special register number.
1516 regnum_to_srnum(regno
)
1520 case VAB_REGNUM
: return(0);
1521 case OPS_REGNUM
: return(1);
1522 case CPS_REGNUM
: return(2);
1523 case CFG_REGNUM
: return(3);
1524 case CHA_REGNUM
: return(4);
1525 case CHD_REGNUM
: return(5);
1526 case CHC_REGNUM
: return(6);
1527 case RBP_REGNUM
: return(7);
1528 case TMC_REGNUM
: return(8);
1529 case TMR_REGNUM
: return(9);
1530 case NPC_REGNUM
: return(USE_SHADOW_PC
? (20) : (10));
1531 case PC_REGNUM
: return(USE_SHADOW_PC
? (21) : (11));
1532 case PC2_REGNUM
: return(USE_SHADOW_PC
? (22) : (12));
1533 case MMU_REGNUM
: return(13);
1534 case LRU_REGNUM
: return(14);
1535 case IPC_REGNUM
: return(128);
1536 case IPA_REGNUM
: return(129);
1537 case IPB_REGNUM
: return(130);
1538 case Q_REGNUM
: return(131);
1539 case ALU_REGNUM
: return(132);
1540 case BP_REGNUM
: return(133);
1541 case FC_REGNUM
: return(134);
1542 case CR_REGNUM
: return(135);
1543 case FPE_REGNUM
: return(160);
1544 case INTE_REGNUM
: return(161);
1545 case FPS_REGNUM
: return(162);
1546 case EXO_REGNUM
:return(164);
1548 return(255); /* Failure ? */
1551 /****************************************************************************/
1553 * Determine the Target memory space qualifier based on the addr.
1554 * FIXME: Can't distinguis I_ROM/D_ROM.
1555 * FIXME: Doesn't know anything about I_CACHE/D_CACHE.
1558 udi_memory_space(addr
)
1561 UDIUInt32 tstart
= IMemStart
;
1562 UDIUInt32 tend
= tstart
+ IMemSize
;
1563 UDIUInt32 dstart
= DMemStart
;
1564 UDIUInt32 dend
= tstart
+ DMemSize
;
1565 UDIUInt32 rstart
= RMemStart
;
1566 UDIUInt32 rend
= tstart
+ RMemSize
;
1568 if (((UDIUInt32
)addr
>= tstart
) && ((UDIUInt32
)addr
< tend
)) {
1569 return UDI29KIRAMSpace
;
1570 } else if (((UDIUInt32
)addr
>= dstart
) && ((UDIUInt32
)addr
< dend
)) {
1571 return UDI29KDRAMSpace
;
1572 } else if (((UDIUInt32
)addr
>= rstart
) && ((UDIUInt32
)addr
< rend
)) {
1573 /* FIXME: how do we determine between D_ROM and I_ROM */
1574 return UDI29KIROMSpace
;
1575 } else /* FIXME: what do me do now? */
1576 return UDI29KDRAMSpace
; /* Hmmm! */
1578 /*********************************************************************** STUBS
1581 void convert16() {;}
1582 void convert32() {;}
1583 GDB_FILE
* EchoFile
= 0; /* used for debugging */
1584 int QuietMode
= 0; /* used for debugging */
1586 #ifdef NO_HIF_SUPPORT
1590 return(0); /* Emulate a failure */
1594 /* Target_ops vector. Not static because there does not seem to be
1595 any portable way to do a forward declaration of a static variable.
1596 The RS/6000 doesn't like "extern" followed by "static"; SunOS
1597 /bin/cc doesn't like "static" twice. */
1599 struct target_ops udi_ops
= {
1601 "Remote UDI connected TIP",
1602 "Remote debug an AMD 29k using UDI socket connection to TIP process.\n\
1604 `configuration-id AF_INET hostname port-number'\n\
1605 To connect via the network, where hostname and port-number specify the\n\
1606 host and port where you can connect via UDI.\n\
1607 configuration-id is unused.\n\
1609 `configuration-id AF_UNIX socket-name tip-program'\n\
1610 To connect using a local connection to the \"tip.exe\" program which is\n\
1611 supplied by AMD. If socket-name specifies an AF_UNIX socket then the\n\
1612 tip program must already be started; connect to it using that socket.\n\
1613 If not, start up tip-program, which should be the name of the tip\n\
1614 program. If appropriate, the PATH environment variable is searched.\n\
1615 configuration-id is unused.\n\
1617 `configuration-id'\n\
1618 Look up the configuration in ./udi_soc or /etc/udi_soc, which\n\
1619 are files containing lines in the above formats. configuration-id is\n\
1620 used to pick which line of the file to use.",
1627 udi_fetch_registers
,
1628 udi_store_registers
,
1629 udi_prepare_to_store
,
1630 udi_xfer_inferior_memory
,
1632 udi_insert_breakpoint
,
1633 udi_remove_breakpoint
,
1634 0, /* termial_init */
1635 0, /* terminal_inferior */
1636 0, /* terminal_ours_for_output */
1637 0, /* terminal_ours */
1638 0, /* terminal_info */
1639 udi_kill
, /* FIXME, kill */
1641 0, /* lookup_symbol */
1642 udi_create_inferior
,
1643 udi_mourn
, /* mourn_inferior FIXME */
1645 0, /* notice_signals */
1648 1, /* has_all_memory */
1651 1, /* has_registers */
1652 1, /* has_execution */
1654 0, /* sections_end */
1655 OPS_MAGIC
, /* Always the last thing */
1659 _initialize_remote_udi ()
1661 add_target (&udi_ops
);