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. Because we are only attempting to
31 use this module to debug our kernel, which is already loaded when
32 gdb is started up, I did not code up the file downloading facilities.
33 As a result this module has only the stubs to download files.
34 You should get tagged at compile time if you need to make any
36 - Daniel Mann at AMD took the 3.95 adaptions above and replaced
37 MiniMON interface with UDI-p interface. */
50 #include "29k-share/udi/udiproc.h"
53 /* access the register store directly, without going through
54 the normal handler functions. This avoids an extra data copy. */
57 extern int stop_soon_quietly
; /* for wait_for_inferior */
58 extern struct value
*call_function_by_hand();
59 static void udi_resume();
60 static void udi_fetch_registers ();
61 static void udi_load();
62 static void fetch_register ();
63 static void udi_store_registers ();
64 static int store_register ();
65 static int regnum_to_srnum();
66 static void udi_close ();
67 static CPUSpace
udi_memory_space();
68 static int udi_write_inferior_memory();
69 static int udi_read_inferior_memory();
70 char CoffFileName
[100] = "";
74 #define TYPE_UNKNOWN 0
78 static char *processor_name
[] = { "Unknown", "Am29000", "Am29030", "Am29050" };
79 static int processor_type
=TYPE_UNKNOWN
;
80 #define FREEZE_MODE (read_register(CPS_REGNUM) && 0x400)
81 #define USE_SHADOW_PC ((processor_type == TYPE_A29050) && FREEZE_MODE)
83 #define LLOG_FILE "udi.log"
84 #if defined (LOG_FILE)
88 static int timeout
= 5;
89 extern struct target_ops udi_ops
; /* Forward declaration */
91 /* Special register enumeration.
94 /******************************************************************* UDI DATA*/
95 #define MAXDATA 2*1024 /* max UDI[read/write] byte size */
96 /* Descriptor for I/O to remote machine. Initialize it to -1 so that
97 udi_open knows that we don't have a file open when the program
99 UDISessionId udi_session_id
= -1;
101 CPUOffset IMemStart
= 0;
102 CPUSizeT IMemSize
= 0;
103 CPUOffset DMemStart
= 0;
104 CPUSizeT DMemSize
= 0;
105 CPUOffset RMemStart
= 0;
106 CPUSizeT RMemSize
= 0;
110 #define SBUF_MAX 1024 /* maximum size of string handling buffer */
113 typedef struct bkpt_entry_str
118 unsigned int BreakId
;
120 #define BKPT_TABLE_SIZE 40
121 static bkpt_entry_t bkpt_table
[BKPT_TABLE_SIZE
];
122 extern char dfe_errmsg
[]; /* error string */
124 /*********************************************************** SIGNAL SUPPORT */
125 /* Called when SIGALRM signal sent due to alarm() timeout. */
130 # define volatile /**/
133 volatile int n_alarms
;
140 printf ("udi_timer called\n");
144 #endif /* HAVE_TERMIO */
146 /* malloc'd name of the program on the remote system. */
147 static char *prog_name
= NULL
;
150 /* Number of SIGTRAPs we need to simulate. That is, the next
151 NEED_ARTIFICIAL_TRAP calls to udi_wait should just return
152 SIGTRAP without actually waiting for anything. */
154 /******************************************************* UDI_CREATE_INFERIOR */
155 /* This is called not only when we first attach, but also when the
156 user types "run" after having attached. */
158 udi_create_inferior (execfile
, args
, env
)
165 { if (prog_name
!= NULL
)
167 prog_name
= savestring (execfile
, strlen (execfile
));
170 if (prog_name
== 0 /* || exec_bfd == 0 */ )
171 error ("No exec file specified");
173 if (udi_session_id
< 0){
174 printf("UDI connection not open yet.\n");
178 inferior_pid
= 40000;
180 #if defined(ULTRA3) && defined(KERNEL_DEBUGGING)
181 /* On ultra3 (NYU) we assume the kernel is already running so there is
182 * no file to download
188 init_wait_for_inferior ();
189 clear_proceed_status ();
192 /******************************************************* UDI_MOURN_INFERIOR */
196 pop_target (); /* Pop back to no-child state */
197 generic_mourn_inferior ();
200 /******************************************************************** UDI_OPEN
201 ** Open a connection to remote TIP.
202 NAME is the socket domain used for communication with the TIP,
203 then a space and the socket name or TIP-host name.
204 '<udi_udi_config_id> [progname]' for example.
207 /* XXX - need cleanups for udiconnect for various failures!!! */
209 static char *udi_config_id
;
211 udi_open (name
, from_tty
)
218 UDIMemoryRange KnownMemory
[10];
219 UDIUInt32 ChipVersions
[10];
220 UDIInt NumberOfRanges
= 10;
221 UDIInt NumberOfChips
= 10;
223 UDIUInt32 TIPId
, TargetId
, DFEId
, DFE
, TIP
, DFEIPCId
, TIPIPCId
;
225 target_preopen(from_tty
);
227 /* Find the first whitespace character, it separates udi_config_id
229 if(!name
) goto erroid
;
231 *p
!= '\0' && !isspace (*p
); p
++)
235 error("Usage: target udi config_id progname, where config_id appears in udi_soc file");
237 udi_config_id
= (char*)malloc (p
- name
+ 1);
238 strncpy (udi_config_id
, name
, p
- name
);
239 udi_config_id
[p
- name
] = '\0';
241 /* Skip over the whitespace after udi_config_id */
242 for (; isspace (*p
); p
++)
245 if (prog_name
!= NULL
)
247 prog_name
= savestring (p
, strlen (p
));
249 if (UDIConnect(udi_config_id
, &udi_session_id
))
250 error("UDIConnect() failed: %s\n", dfe_errmsg
);
252 push_target (&udi_ops
);
255 #ifndef NO_SIGINTERRUPT
256 /* Cause SIGALRM's to make reads fail with EINTR instead of resuming
258 if (siginterrupt (SIGALRM
, 1) != 0)
259 error ("udi_open: siginterrupt() %s", safe_strerror(errno
));
262 /* Set up read timeout timer. */
263 if ((void (*)) signal (SIGALRM
, udi_timer
) == (void (*)) -1)
264 error ("udi_open: signal() %s", safe_strerror(errno
));
267 #if defined (LOG_FILE)
268 log_file
= fopen (LOG_FILE
, "w");
269 if (log_file
== NULL
)
270 error ("udi_open: fopen(%s) %s", LOG_FILE
, safe_strerror(errno
));
273 ** Initialize target configuration structure (global)
275 if(UDIGetTargetConfig( KnownMemory
, &NumberOfRanges
,
276 ChipVersions
, &NumberOfChips
))
277 error ("UDIGetTargetConfig() failed");
278 if(NumberOfChips
> 2)
279 fprintf(stderr
,"Taret has more than one processor\n");
280 for(cnt
=0; cnt
<NumberOfRanges
; cnt
++)
281 { switch(KnownMemory
[cnt
].Space
)
283 default: fprintf(stderr
, "UDIGetTargetConfig() unknown memory space\n");
287 case UDI29KIROMSpace
:
288 RMemStart
= KnownMemory
[cnt
].Offset
;
289 RMemSize
= KnownMemory
[cnt
].Size
;
291 case UDI29KIRAMSpace
:
292 IMemStart
= KnownMemory
[cnt
].Offset
;
293 IMemSize
= KnownMemory
[cnt
].Size
;
295 case UDI29KDRAMSpace
:
296 DMemStart
= KnownMemory
[cnt
].Offset
;
297 DMemSize
= KnownMemory
[cnt
].Size
;
302 /* Determine the processor revision level */
303 prl
= (unsigned int)read_register(CFG_REGNUM
) >> 24;
305 { fprintf_filtered(stderr
,
306 "Remote debugging Am29000 rev %c\n",'A'+(prl
&0x1f));
307 processor_type
= TYPE_A29000
;
308 } else if ((prl
&0xe0) == 0x40) /* 29030 = 0x4* */
309 { fprintf_filtered(stderr
,
310 "Remote debugging Am2903* rev %c\n",'A'+(prl
&0x1f));
311 processor_type
= TYPE_A29030
;
312 } else if ((prl
&0xe0) == 0x20) /* 29050 = 0x2* */
313 { fprintf_filtered(stderr
,
314 "Remote debugging Am29050 rev %c\n",'A'+(prl
&0x1f));
315 processor_type
= TYPE_A29050
;
317 processor_type
= TYPE_UNKNOWN
;
318 fprintf_filtered(stderr
,"WARNING: processor type unknown.\n");
320 if(UDICreateProcess(&PId
))
321 fprintf(stderr
, "UDICreateProcess() failed\n");
323 /* Print out some stuff, letting the user now what's going on */
324 if(UDICapabilities( &TIPId
, &TargetId
, DFEId
, DFE
, &TIP
, &DFEIPCId
,
326 error ("UDICapabilities() failed");
328 printf_filtered("Remote debugging an %s connected via UDI socket,\n\
329 DFE-IPC version %x.%x.%x TIP-IPC version %x.%x.%x TIP version %x.%x.%x\n %s\n",
330 processor_name
[processor_type
],
331 (DFEIPCId
>>8)&0xf, (DFEIPCId
>>4)&0xf, DFEIPCId
&0xf,
332 (TIPIPCId
>>8)&0xf, (TIPIPCId
>>4)&0xf, TIPIPCId
&0xf,
333 (TargetId
>>8)&0xf, (TargetId
>>4)&0xf, TargetId
&0xf,
336 /* FIXME: can this restriction be removed? */
337 printf_filtered("Remote debugging using virtual addresses works only\n");
338 printf_filtered(" when virtual addresses map 1:1 to physical addresses.\n");
342 if (processor_type
!= TYPE_A29050
) {
343 fprintf_filtered(stderr
,
344 "Freeze-mode debugging can only be done on an Am29050,\n");
345 fprintf_filtered(stderr
,
346 " unless GDB is being used with a 29K simulator.\n");
351 /******************************************************************* UDI_CLOSE
352 Close the open connection to the TIP process.
353 Use this when you want to detach and do something else
356 udi_close (quitting
) /*FIXME: how is quitting used */
361 if (udi_session_id
< 0)
362 error ("Can't close udi connection: not debugging remotely.");
364 /* We should never get here if there isn't something valid in
367 if(UDIDisconnect(udi_stream, Terminate);)
368 error ("UDIDisconnect() failed in udi_close");
370 /* Do not try to close udi_session_id again, later in the program. */
374 #if defined (LOG_FILE)
375 if (ferror (log_file
))
376 printf ("Error writing log file.\n");
377 if (fclose (log_file
) != 0)
378 printf ("Error closing log file.\n");
381 printf_filtered (" Ending remote debugging\n");
384 /**************************************************************** UDI_ATACH */
385 /* Attach to a program that is already loaded and running
386 * Upon exiting the process's execution is stopped.
389 udi_attach (args
, from_tty
)
398 UDIBool HostEndian
= 0;
400 if (udi_session_id
< 0)
401 error ("UDI connection not opened yet, use the 'target udi' command.\n");
404 printf ("Attaching to remote program %s...\n", prog_name
);
408 From
.Offset
= UDI29KSpecialRegs
;
409 if(UDIRead(From
, &PC_adds
, Count
, Size
, &CountDone
, HostEndian
))
410 error ("UDIRead failed in udi_attach");
411 printf ("Remote process is now halted, pc1 = 0x%x.\n", PC_adds
);
413 /************************************************************* UDI_DETACH */
414 /* Terminate the open connection to the TIP process.
415 Use this when you want to detach and do something else
416 with your gdb. Leave remote process running (with no breakpoints set). */
418 udi_detach (args
,from_tty
)
422 remove_breakpoints(); /* Just in case there were any left in */
423 if(UDIDisconnect(udi_session_id
))
424 error ("UDIDisconnect() failed in udi_detach");
425 pop_target(); /* calls udi_close to do the real work */
427 printf ("Ending remote debugging\n");
431 /****************************************************************** UDI_RESUME
432 ** Tell the remote machine to resume. */
435 udi_resume (step
, sig
)
440 UDIStepType StepType
= UDIStepNatural
;
443 if (step
) /* step 1 instruction */
445 tip_error
= UDIStep (Steps
, StepType
, Range
);
449 fprintf (stderr
, "UDIStep() error = %d\n", tip_error
);
450 error ("failed in udi_resume");
454 error ("UDIExecute() failed in udi_resume");
457 /******************************************************************** UDI_WAIT
458 ** Wait until the remote machine stops, then return,
459 storing status in STATUS just as `wait' would. */
469 int old_timeout
= timeout
;
470 int old_immediate_quit
= immediate_quit
;
473 WSETEXIT ((*status
), 0);
475 /* wait for message to arrive. It should be:
476 If the target stops executing, udi_wait() should return.
478 timeout
= 0; /* Wait indefinetly for a message */
479 immediate_quit
= 1; /* Helps ability to QUIT */
484 MaxTime
= UDIWaitForever
;
485 UDIWait(MaxTime
, &PId
, &StopReason
);
486 QUIT
; /* Let user quit if they want */
488 switch (StopReason
& UDIGrossState
)
491 if (UDIGetStdout (sbuf
, (UDISizeT
)SBUF_MAX
, &CountDone
))
492 error ("UDIGetStdin() failed in udi_wait");
493 fwrite (sbuf
, 1, CountDone
, stdout
);
497 UDIGetStderr (sbuf
, (UDISizeT
)SBUF_MAX
, &CountDone
);
498 fwrite (sbuf
, 1, CountDone
, stderr
);
502 printf("DEBUG: stdin requested ... continue\n");
503 /* UDIPutStdin(sbuf, (UDISizeT)i, &CountDone); */
513 switch (StopReason
& UDIGrossState
)
516 printf("Am290*0 received vector number %d\n", StopReason
>> 24);
518 switch (StopReason
>> 8)
520 case 0: /* Illegal opcode */
521 printf(" (break point)\n");
522 WSETSTOP ((*status
), SIGTRAP
);
524 case 1: /* Unaligned Access */
525 WSETSTOP ((*status
), SIGBUS
);
529 WSETSTOP ((*status
), SIGFPE
);
531 case 5: /* Protection Violation */
532 WSETSTOP ((*status
), SIGILL
);
536 case 8: /* User Instruction Mapping Miss */
537 case 9: /* User Data Mapping Miss */
538 case 10: /* Supervisor Instruction Mapping Miss */
539 case 11: /* Supervisor Data Mapping Miss */
540 WSETSTOP ((*status
), SIGSEGV
);
544 WSETSTOP ((*status
), SIGILL
);
547 WSETSTOP ((*status
), SIGALRM
);
550 WSETSTOP ((*status
), SIGTRAP
);
555 case 19: /* INTR3/Internal */
558 WSETSTOP ((*status
), SIGINT
);
560 case 22: /* Floating-Point Exception */
561 WSETSTOP ((*status
), SIGILL
);
563 case 77: /* assert 77 */
564 WSETSTOP ((*status
), SIGTRAP
);
567 WSETEXIT ((*status
), 0);
570 case UDINotExecuting
:
571 WSETSTOP ((*status
), SIGTERM
);
574 WSETSTOP ((*status
), SIGILL
);
577 WSETSTOP ((*status
), SIGTSTP
);
580 WSETSTOP ((*status
), SIGLOST
);
584 WSETSTOP ((*status
), SIGTRAP
);
587 WSETSTOP ((*status
), SIGSTOP
);
590 WSETSTOP ((*status
), SIGKILL
);
594 WSETEXIT ((*status
), 0);
597 timeout
= old_timeout
; /* Restore original timeout value */
598 immediate_quit
= old_immediate_quit
;
602 /********************************************************** UDI_FETCH_REGISTERS
603 * Read a remote register 'regno'.
604 * If regno==-1 then read all the registers.
607 udi_fetch_registers (regno
)
615 UDIBool HostEndian
= 0;
619 fetch_register(regno
);
625 From
.Space
= UDI29KGlobalRegs
;
627 To
= (UDIUInt32
*)®isters
[4 * GR1_REGNUM
];
629 if (UDIRead(From
, To
, Count
, Size
, &CountDone
, HostEndian
))
630 error("UDIRead() failed in udi_fetch_registers");
632 register_valid
[GR1_REGNUM
] = 1;
634 #if defined(GR64_REGNUM) /* Read gr64-127 */
636 /* Global Registers gr64-gr95 */
638 From
.Space
= UDI29KGlobalRegs
;
640 To
= (UDIUInt32
*)®isters
[4 * GR64_REGNUM
];
642 if (UDIRead(From
, To
, Count
, Size
, &CountDone
, HostEndian
))
643 error("UDIRead() failed in udi_fetch_registers");
645 for (i
= GR64_REGNUM
; i
< GR64_REGNUM
+ 32; i
++)
646 register_valid
[i
] = 1;
648 #endif /* GR64_REGNUM */
650 /* Global Registers gr96-gr127 */
652 From
.Space
= UDI29KGlobalRegs
;
654 To
= (UDIUInt32
*)®isters
[4 * GR96_REGNUM
];
656 if (UDIRead(From
, To
, Count
, Size
, &CountDone
, HostEndian
))
657 error("UDIRead() failed in udi_fetch_registers");
659 for (i
= GR96_REGNUM
; i
< GR96_REGNUM
+ 32; i
++)
660 register_valid
[i
] = 1;
662 /* Local Registers */
664 From
.Space
= UDI29KLocalRegs
;
666 To
= (UDIUInt32
*)®isters
[4 * LR0_REGNUM
];
668 if (UDIRead(From
, To
, Count
, Size
, &CountDone
, HostEndian
))
669 error("UDIRead() failed in udi_fetch_registers");
671 for (i
= LR0_REGNUM
; i
< LR0_REGNUM
+ 128; i
++)
672 register_valid
[i
] = 1;
674 /* Protected Special Registers */
676 From
.Space
= UDI29KSpecialRegs
;
678 To
= (UDIUInt32
*)®isters
[4 * SR_REGNUM(0)];
680 if (UDIRead(From
, To
, Count
, Size
, &CountDone
, HostEndian
))
681 error("UDIRead() failed in udi_fetch_registers");
683 for (i
= SR_REGNUM(0); i
< SR_REGNUM(0) + 15; i
++)
684 register_valid
[i
] = 1;
686 if (USE_SHADOW_PC
) { /* Let regno_to_srnum() handle the register number */
687 fetch_register(NPC_REGNUM
);
688 fetch_register(PC_REGNUM
);
689 fetch_register(PC2_REGNUM
);
691 /* Unprotected Special Registers sr128-sr135 */
693 From
.Space
= UDI29KSpecialRegs
;
695 To
= (UDIUInt32
*)®isters
[4 * SR_REGNUM(128)];
697 if (UDIRead(From
, To
, Count
, Size
, &CountDone
, HostEndian
))
698 error("UDIRead() failed in udi_fetch_registers");
700 for (i
= SR_REGNUM(128); i
< SR_REGNUM(128) + 135-128+1; i
++)
701 register_valid
[i
] = 1;
706 printf("Fetching all registers\n");
707 printf("Fetching PC0 = 0x%x, PC1 = 0x%x, PC2 = 0x%x\n",
708 read_register(NPC_REGNUM
), read_register(PC_REGNUM
),
709 read_register(PC2_REGNUM
));
712 /* There doesn't seem to be any way to get these. */
715 supply_register (FPE_REGNUM
, (char *) &val
);
716 supply_register (INTE_REGNUM
, (char *) &val
);
717 supply_register (FPS_REGNUM
, (char *) &val
);
718 supply_register (EXO_REGNUM
, (char *) &val
);
723 /********************************************************* UDI_STORE_REGISTERS
724 ** Store register regno into the target.
725 * If regno==-1 then store all the registers.
729 udi_store_registers (regno
)
737 UDIBool HostEndian
= 0;
741 store_register(regno
);
747 printf("Storing all registers\n");
748 printf("PC0 = 0x%x, PC1 = 0x%x, PC2 = 0x%x\n", read_register(NPC_REGNUM
),
749 read_register(PC_REGNUM
), read_register(PC2_REGNUM
));
754 From
= (UDIUInt32
*)®isters
[4 * GR1_REGNUM
];
755 To
.Space
= UDI29KGlobalRegs
;
758 if(UDIWrite(From
, To
, Count
, Size
, &CountDone
, HostEndian
))
759 error("UDIWrite() failed in udi_store_regisetrs");
761 #if defined(GR64_REGNUM)
763 /* Global registers gr64-gr95 */
765 From
= (UDIUInt32
*)®isters
[4 * GR64_REGNUM
];
766 To
.Space
= UDI29KGlobalRegs
;
769 if(UDIWrite(From
, To
, Count
, Size
, &CountDone
, HostEndian
))
770 error("UDIWrite() failed in udi_store_regisetrs");
772 #endif /* GR64_REGNUM */
774 /* Global registers gr96-gr127 */
776 From
= (UDIUInt32
*)®isters
[4 * GR96_REGNUM
];
777 To
.Space
= UDI29KGlobalRegs
;
780 if(UDIWrite(From
, To
, Count
, Size
, &CountDone
, HostEndian
))
781 error("UDIWrite() failed in udi_store_regisetrs");
783 /* Local Registers */
785 From
= (UDIUInt32
*)®isters
[4 * LR0_REGNUM
];
786 To
.Space
= UDI29KLocalRegs
;
789 if(UDIWrite(From
, To
, Count
, Size
, &CountDone
, HostEndian
))
790 error("UDIWrite() failed in udi_store_regisetrs");
793 /* Protected Special Registers */ /* VAB through TMR */
795 From
= (UDIUInt32
*)®isters
[4 * SR_REGNUM(0)];
796 To
.Space
= UDI29KSpecialRegs
;
799 if(UDIWrite(From
, To
, Count
, Size
, &CountDone
, HostEndian
))
800 error("UDIWrite() failed in udi_store_regisetrs");
802 /* PC0, PC1, PC2 possibly as shadow registers */
804 From
= (UDIUInt32
*)®isters
[4 * SR_REGNUM(10)];
805 To
.Space
= UDI29KSpecialRegs
;
808 To
.Offset
= 20; /* SPC0 */
810 To
.Offset
= 10; /* PC0 */
811 if(UDIWrite(From
, To
, Count
, Size
, &CountDone
, HostEndian
))
812 error("UDIWrite() failed in udi_store_regisetrs");
816 From
= (UDIUInt32
*)®isters
[4 * SR_REGNUM(13)];
817 To
.Space
= UDI29KSpecialRegs
;
820 if(UDIWrite(From
, To
, Count
, Size
, &CountDone
, HostEndian
))
821 error("UDIWrite() failed in udi_store_regisetrs");
823 /* Unprotected Special Registers */
825 From
= (UDIUInt32
*)®isters
[4 * SR_REGNUM(128)];
826 To
.Space
= UDI29KSpecialRegs
;
829 if(UDIWrite(From
, To
, Count
, Size
, &CountDone
, HostEndian
))
830 error("UDIWrite() failed in udi_store_regisetrs");
832 registers_changed ();
835 /****************************************************** UDI_PREPARE_TO_STORE */
836 /* Get ready to modify the registers array. On machines which store
837 individual registers, this doesn't need to do anything. On machines
838 which store all the registers in one fell swoop, this makes sure
839 that registers contains all the registers from the program being
843 udi_prepare_to_store ()
845 /* Do nothing, since we can store individual regs */
848 /********************************************************** TRANSLATE_ADDR */
853 #if defined(ULTRA3) && defined(KERNEL_DEBUGGING)
854 /* Check for a virtual address in the kernel */
855 /* Assume physical address of ublock is in paddr_u register */
856 /* FIXME: doesn't work for user virtual addresses */
857 if (addr
>= UVADDR
) {
858 /* PADDR_U register holds the physical address of the ublock */
859 CORE_ADDR i
= (CORE_ADDR
)read_register(PADDR_U_REGNUM
);
860 return(i
+ addr
- (CORE_ADDR
)UVADDR
);
868 /************************************************* UDI_XFER_INFERIOR_MEMORY */
869 /* FIXME! Merge these two. */
871 udi_xfer_inferior_memory (memaddr
, myaddr
, len
, write
)
878 memaddr
= translate_addr(memaddr
);
881 return udi_write_inferior_memory (memaddr
, myaddr
, len
);
883 return udi_read_inferior_memory (memaddr
, myaddr
, len
);
886 /********************************************************** UDI_FILES_INFO */
890 printf ("\tAttached to UDI socket to %s and running program %s.\n",
891 udi_config_id
, prog_name
);
894 /**************************************************** UDI_INSERT_BREAKPOINT */
896 udi_insert_breakpoint (addr
, contents_cache
)
898 char *contents_cache
;
903 for (cnt
= 0; cnt
< BKPT_TABLE_SIZE
; cnt
++)
904 if (bkpt_table
[cnt
].Type
== 0) /* Find first free slot */
907 if(cnt
>= BKPT_TABLE_SIZE
)
908 error("Too many breakpoints set");
910 bkpt_table
[cnt
].Addr
.Offset
= addr
;
911 bkpt_table
[cnt
].Addr
.Space
= UDI29KIRAMSpace
;
912 bkpt_table
[cnt
].PassCount
= 1;
913 bkpt_table
[cnt
].Type
= UDIBreakFlagExecute
;
915 err
= UDISetBreakpoint(bkpt_table
[cnt
].Addr
,
916 bkpt_table
[cnt
].PassCount
,
917 bkpt_table
[cnt
].Type
,
918 &bkpt_table
[cnt
].BreakId
);
920 if (err
== 0) return 0; /* Success */
922 bkpt_table
[cnt
].Type
= 0;
923 error("UDISetBreakpoint returned error code %d\n", err
);
926 /**************************************************** UDI_REMOVE_BREAKPOINT */
928 udi_remove_breakpoint (addr
, contents_cache
)
930 char *contents_cache
;
935 for (cnt
= 0; cnt
< BKPT_TABLE_SIZE
; cnt
++)
936 if (bkpt_table
[cnt
].Addr
.Offset
== addr
) /* Find matching breakpoint */
939 if(cnt
>= BKPT_TABLE_SIZE
)
940 error("Can't find breakpoint in table");
942 bkpt_table
[cnt
].Type
= 0;
944 err
= UDIClearBreakpoint(bkpt_table
[cnt
].BreakId
);
945 if (err
== 0) return 0; /* Success */
947 error("UDIClearBreakpoint returned error code %d\n", err
);
950 /***************************************************************** UDI_KILL */
952 udi_kill(arg
,from_tty
)
958 #if defined(ULTRA3) && defined(KERNEL_DEBUGGING)
959 /* We don't ever kill the kernel */
961 printf_filtered("Kernel not killed, but left in current state.\n");
962 printf_filtered("Use detach to leave kernel running.\n");
968 printf("Target has been stopped.");
976 /***************************************************************** UDI_LOAD */
978 * Load a program into the target.
981 udi_load(arg_string
,from_tty
)
985 #define MAX_TOKENS 25
986 #define BUFFER_SIZE 256
988 char *token
[MAX_TOKENS
];
989 char cmd_line
[BUFFER_SIZE
];
993 #if defined(KERNEL_DEBUGGING) && defined(ULTRA3)
994 printf("The kernel had better be loaded already! Loading not done.\n");
997 error ("No program name");
998 arg_string
= tilde_expand (arg_string
);
999 sprintf(cmd_line
,"y %s %s", prog_name
, arg_string
);
1002 token
[0] = cmd_line
;
1004 if (cmd_line
[0] != '\0')
1005 { token
[token_count
] = strtok(cmd_line
, " \t,;\n\r");
1007 if (token
[token_count
] != NULL
)
1009 token_count
= token_count
+ 1;
1010 token
[token_count
] = strtok((char *) NULL
, " \t,;\n\r");
1011 } while ((token
[token_count
] != NULL
) &&
1012 (token_count
< MAX_TOKENS
));
1017 make_cleanup (free
, arg_string
);
1020 if(yank_cmd(token
, token_count
))
1021 error("Failure when tring to load program");
1023 symbol_file_add (prog_name
, from_tty
, 0, 0, 0, 0);/*DEBUG need to add text_addr */
1028 /*************************************************** UDI_WRITE_INFERIOR_MEMORY
1029 ** Copy LEN bytes of data from debugger memory at MYADDR
1030 to inferior's memory at MEMADDR. Returns number of bytes written. */
1032 udi_write_inferior_memory (memaddr
, myaddr
, len
)
1042 UDICount CountDone
= 0;
1043 UDIBool HostEndian
= 0;
1045 To
.Space
= udi_memory_space(memaddr
);
1046 From
= (UDIUInt32
*)myaddr
;
1048 while (nwritten
< len
)
1049 { Count
= len
- nwritten
;
1050 if (Count
> MAXDATA
) Count
= MAXDATA
;
1051 To
.Offset
= memaddr
+ nwritten
;
1052 if(UDIWrite(From
, To
, Count
, Size
, &CountDone
, HostEndian
))
1053 { error("UDIWrite() failed in udi_write_inferrior_memory");
1057 { nwritten
+= CountDone
;
1064 /**************************************************** UDI_READ_INFERIOR_MEMORY
1065 ** Read LEN bytes from inferior memory at MEMADDR. Put the result
1066 at debugger address MYADDR. Returns number of bytes read. */
1068 udi_read_inferior_memory(memaddr
, myaddr
, len
)
1078 UDICount CountDone
= 0;
1079 UDIBool HostEndian
= 0;
1081 From
.Space
= udi_memory_space(memaddr
);
1082 To
= (UDIUInt32
*)myaddr
;
1085 { Count
= len
- nread
;
1086 if (Count
> MAXDATA
) Count
= MAXDATA
;
1087 From
.Offset
= memaddr
+ nread
;
1088 if(UDIRead(From
, To
, Count
, Size
, &CountDone
, HostEndian
))
1089 { error("UDIWrite() failed in udi_read_inferrior_memory");
1093 { nread
+= CountDone
;
1100 /********************************************************************* WARNING
1105 error ("ERROR while loading program into remote TIP: $d\n", num
);
1109 /*****************************************************************************/
1110 /* Fetch a single register indicatated by 'regno'.
1111 * Returns 0/-1 on success/failure.
1114 fetch_register (regno
)
1122 UDIBool HostEndian
= 0;
1125 if (regno
== GR1_REGNUM
)
1127 From
.Space
= UDI29KGlobalRegs
;
1130 else if (regno
>= GR96_REGNUM
&& regno
< GR96_REGNUM
+ 32)
1132 From
.Space
= UDI29KGlobalRegs
;
1133 From
.Offset
= (regno
- GR96_REGNUM
) + 96;;
1136 #if defined(GR64_REGNUM)
1138 else if (regno
>= GR64_REGNUM
&& regno
< GR64_REGNUM
+ 32 )
1140 From
.Space
= UDI29KGlobalRegs
;
1141 From
.Offset
= (regno
- GR64_REGNUM
) + 64;
1144 #endif /* GR64_REGNUM */
1146 else if (regno
>= LR0_REGNUM
&& regno
< LR0_REGNUM
+ 128)
1148 From
.Space
= UDI29KLocalRegs
;
1149 From
.Offset
= (regno
- LR0_REGNUM
);
1151 else if (regno
>=FPE_REGNUM
&& regno
<=EXO_REGNUM
)
1154 supply_register(160 + (regno
- FPE_REGNUM
),(char *) &val
);
1155 return; /* Pretend Success */
1159 From
.Space
= UDI29KSpecialRegs
;
1160 From
.Offset
= regnum_to_srnum(regno
);
1163 if (UDIRead(From
, &To
, Count
, Size
, &CountDone
, HostEndian
))
1164 error("UDIRead() failed in udi_fetch_registers");
1166 supply_register(regno
, (char *) &To
);
1169 printf("Fetching register %s = 0x%x\n", reg_names
[regno
], To
);
1171 /*****************************************************************************/
1172 /* Store a single register indicated by 'regno'.
1173 * Returns 0/-1 on success/failure.
1176 store_register (regno
)
1185 UDIBool HostEndian
= 0;
1187 From
= read_register (regno
); /* get data value */
1190 printf("Storing register %s = 0x%x\n", reg_names
[regno
], From
);
1192 if (regno
== GR1_REGNUM
)
1193 { To
.Space
= UDI29KGlobalRegs
;
1195 result
= UDIWrite(&From
, To
, Count
, Size
, &CountDone
, HostEndian
);
1196 /* Setting GR1 changes the numbers of all the locals, so invalidate the
1197 * register cache. Do this *after* calling read_register, because we want
1198 * read_register to return the value that write_register has just stuffed
1199 * into the registers array, not the value of the register fetched from
1202 registers_changed ();
1204 #if defined(GR64_REGNUM)
1205 else if (regno
>= GR64_REGNUM
&& regno
< GR64_REGNUM
+ 32 )
1206 { To
.Space
= UDI29KGlobalRegs
;
1207 To
.Offset
= (regno
- GR64_REGNUM
) + 64;
1208 result
= UDIWrite(&From
, To
, Count
, Size
, &CountDone
, HostEndian
);
1210 #endif /* GR64_REGNUM */
1211 else if (regno
>= GR96_REGNUM
&& regno
< GR96_REGNUM
+ 32)
1212 { To
.Space
= UDI29KGlobalRegs
;
1213 To
.Offset
= (regno
- GR96_REGNUM
) + 96;
1214 result
= UDIWrite(&From
, To
, Count
, Size
, &CountDone
, HostEndian
);
1216 else if (regno
>= LR0_REGNUM
&& regno
< LR0_REGNUM
+ 128)
1217 { To
.Space
= UDI29KLocalRegs
;
1218 To
.Offset
= (regno
- LR0_REGNUM
);
1219 result
= UDIWrite(&From
, To
, Count
, Size
, &CountDone
, HostEndian
);
1221 else if (regno
>=FPE_REGNUM
&& regno
<=EXO_REGNUM
)
1223 return 0; /* Pretend Success */
1225 else /* An unprotected or protected special register */
1226 { To
.Space
= UDI29KSpecialRegs
;
1227 To
.Offset
= regnum_to_srnum(regno
);
1228 result
= UDIWrite(&From
, To
, Count
, Size
, &CountDone
, HostEndian
);
1233 error("UDIWrite() failed in store_registers");
1237 /********************************************************** REGNUM_TO_SRNUM */
1239 * Convert a gdb special register number to a 29000 special register number.
1242 regnum_to_srnum(regno
)
1246 case VAB_REGNUM
: return(0);
1247 case OPS_REGNUM
: return(1);
1248 case CPS_REGNUM
: return(2);
1249 case CFG_REGNUM
: return(3);
1250 case CHA_REGNUM
: return(4);
1251 case CHD_REGNUM
: return(5);
1252 case CHC_REGNUM
: return(6);
1253 case RBP_REGNUM
: return(7);
1254 case TMC_REGNUM
: return(8);
1255 case TMR_REGNUM
: return(9);
1256 case NPC_REGNUM
: return(USE_SHADOW_PC
? (20) : (10));
1257 case PC_REGNUM
: return(USE_SHADOW_PC
? (21) : (11));
1258 case PC2_REGNUM
: return(USE_SHADOW_PC
? (22) : (12));
1259 case MMU_REGNUM
: return(13);
1260 case LRU_REGNUM
: return(14);
1261 case IPC_REGNUM
: return(128);
1262 case IPA_REGNUM
: return(129);
1263 case IPB_REGNUM
: return(130);
1264 case Q_REGNUM
: return(131);
1265 case ALU_REGNUM
: return(132);
1266 case BP_REGNUM
: return(133);
1267 case FC_REGNUM
: return(134);
1268 case CR_REGNUM
: return(135);
1269 case FPE_REGNUM
: return(160);
1270 case INTE_REGNUM
: return(161);
1271 case FPS_REGNUM
: return(162);
1272 case EXO_REGNUM
:return(164);
1274 return(255); /* Failure ? */
1277 /****************************************************************************/
1279 * Determine the Target memory space qualifier based on the addr.
1280 * FIXME: Can't distinguis I_ROM/D_ROM.
1281 * FIXME: Doesn't know anything about I_CACHE/D_CACHE.
1284 udi_memory_space(addr
)
1287 UDIUInt32 tstart
= IMemStart
;
1288 UDIUInt32 tend
= tstart
+ IMemSize
;
1289 UDIUInt32 dstart
= DMemStart
;
1290 UDIUInt32 dend
= tstart
+ DMemSize
;
1291 UDIUInt32 rstart
= RMemStart
;
1292 UDIUInt32 rend
= tstart
+ RMemSize
;
1294 if (((UDIUInt32
)addr
>= tstart
) && ((UDIUInt32
)addr
< tend
)) {
1295 return UDI29KIRAMSpace
;
1296 } else if (((UDIUInt32
)addr
>= dstart
) && ((UDIUInt32
)addr
< dend
)) {
1297 return UDI29KDRAMSpace
;
1298 } else if (((UDIUInt32
)addr
>= rstart
) && ((UDIUInt32
)addr
< rend
)) {
1299 /* FIXME: how do we determine between D_ROM and I_ROM */
1300 return UDI29KIROMSpace
;
1301 } else /* FIXME: what do me do now? */
1302 return UDI29KDRAMSpace
; /* Hmmm! */
1304 /*********************************************************************** STUBS
1307 void convert16() {;}
1308 void convert32() {;}
1309 FILE* EchoFile
= 0; /* used for debugging */
1310 int QuietMode
= 0; /* used for debugging */
1312 /****************************************************************************/
1314 * Define the target subroutine names
1316 static struct target_ops udi_ops
= {
1318 "Remote UDI connected TIP",
1319 "Remote debug an AMD 29k using UDI socket connection to TIP process",
1326 udi_fetch_registers
,
1327 udi_store_registers
,
1328 udi_prepare_to_store
,
1329 udi_xfer_inferior_memory
,
1331 udi_insert_breakpoint
,
1332 udi_remove_breakpoint
,
1333 0, /* termial_init */
1334 0, /* terminal_inferior */
1335 0, /* terminal_ours_for_output */
1336 0, /* terminal_ours */
1337 0, /* terminal_info */
1338 udi_kill
, /* FIXME, kill */
1340 0, /* lookup_symbol */
1341 udi_create_inferior
,
1342 udi_mourn
, /* mourn_inferior FIXME */
1344 0, /* notice_signals */
1347 1, /* has_all_memory */
1350 1, /* has_registers */
1351 1, /* has_execution */
1353 0, /* sections_end */
1354 OPS_MAGIC
, /* Always the last thing */
1357 void _initialize_remote_udi()
1359 add_target (&udi_ops
);
1361 add_set_cmd ("remotedebug", no_class
, var_boolean
,
1363 "Set debugging of UDI I/O.\n\
1364 When enabled, debugging info is displayed.",
1369 #ifdef NO_HIF_SUPPORT
1373 return(0); /* Emulate a failure */