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
, int 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 /* FIXME: Replace with `set remotedebug'. Also, seems not to be used. */
75 #define LLOG_FILE "udi.log"
76 #if defined (LOG_FILE)
80 static int timeout
= 5;
81 extern struct target_ops udi_ops
; /* Forward declaration */
83 /* Special register enumeration.
86 /******************************************************************* UDI DATA*/
87 #define MAXDATA 2*1024 /* max UDI[read/write] byte size */
88 /* Descriptor for I/O to remote machine. Initialize it to -1 so that
89 udi_open knows that we don't have a file open when the program
92 UDISessionId udi_session_id
= -1;
94 CPUOffset IMemStart
= 0;
95 CPUSizeT IMemSize
= 0;
96 CPUOffset DMemStart
= 0;
97 CPUSizeT DMemSize
= 0;
98 CPUOffset RMemStart
= 0;
99 CPUSizeT RMemSize
= 0;
103 UDIMemoryRange address_ranges
[2]; /* Text and data */
104 UDIResource entry
= {0, 0}; /* Entry point */
105 CPUSizeT stack_sizes
[2]; /* Regular and memory stacks */
107 #define SBUF_MAX 1024 /* maximum size of string handling buffer */
110 typedef struct bkpt_entry_str
115 unsigned int BreakId
;
117 #define BKPT_TABLE_SIZE 40
118 static bkpt_entry_t bkpt_table
[BKPT_TABLE_SIZE
];
119 extern char dfe_errmsg
[]; /* error string */
121 /* malloc'd name of the program on the remote system. */
122 static char *prog_name
= NULL
;
124 /* Number of SIGTRAPs we need to simulate. That is, the next
125 NEED_ARTIFICIAL_TRAP calls to udi_wait should just return
126 SIGTRAP without actually waiting for anything. */
128 /* This is called not only when we first attach, but also when the
129 user types "run" after having attached. */
132 udi_create_inferior (execfile
, args
, env
)
141 if (prog_name
!= NULL
)
143 prog_name
= savestring (execfile
, strlen (execfile
));
145 else if (entry
.Offset
)
148 error ("No image loaded into target.");
150 if (udi_session_id
< 0)
152 printf("UDI connection not open yet.\n");
156 inferior_pid
= 40000;
159 download(execfile
, 0);
161 args1
= alloca (strlen(execfile
) + strlen(args
) + 2);
163 strcpy (args1
, execfile
);
165 strcat (args1
, args
);
167 UDIInitializeProcess (address_ranges
, /* ProcessMemory[] */
168 (UDIInt
)2, /* NumberOfRanges */
169 entry
, /* EntryPoint */
170 stack_sizes
, /* *StackSizes */
171 (UDIInt
)2, /* NumberOfStacks */
172 args1
); /* ArgString */
174 init_wait_for_inferior ();
175 clear_proceed_status ();
183 /* Requiring "target udi" each time you run is a major pain. I suspect
184 this was just blindy copied from remote.c, in which "target" and
185 "run" are combined. Having a udi target without an inferior seems
186 to work between "target udi" and "run", so why not now? */
187 pop_target (); /* Pop back to no-child state */
189 generic_mourn_inferior ();
192 /******************************************************************** UDI_OPEN
193 ** Open a connection to remote TIP.
194 NAME is the socket domain used for communication with the TIP,
195 then a space and the socket name or TIP-host name.
196 '<udi_udi_config_id>' for example.
199 /* XXX - need cleanups for udiconnect for various failures!!! */
201 static char *udi_config_id
;
203 udi_open (name
, from_tty
)
210 UDIMemoryRange KnownMemory
[10];
211 UDIUInt32 ChipVersions
[10];
212 UDIInt NumberOfRanges
= 10;
213 UDIInt NumberOfChips
= 10;
215 UDIUInt32 TIPId
, TargetId
, DFEId
, DFE
, TIP
, DFEIPCId
, TIPIPCId
;
217 target_preopen(from_tty
);
221 for (cnt
= 0; cnt
< BKPT_TABLE_SIZE
; cnt
++)
222 bkpt_table
[cnt
].Type
= 0;
225 free (udi_config_id
);
228 error("Usage: target udi config_id, where config_id appears in udi_soc file");
230 udi_config_id
= strdup (strtok (name
, " \t"));
232 if (UDIConnect (udi_config_id
, &udi_session_id
))
233 error("UDIConnect() failed: %s\n", dfe_errmsg
);
235 push_target (&udi_ops
);
237 #if defined (LOG_FILE)
238 log_file
= fopen (LOG_FILE
, "w");
239 if (log_file
== NULL
)
240 error ("udi_open: fopen(%s) %s", LOG_FILE
, safe_strerror(errno
));
243 ** Initialize target configuration structure (global)
245 if (UDIGetTargetConfig (KnownMemory
, &NumberOfRanges
,
246 ChipVersions
, &NumberOfChips
))
247 error ("UDIGetTargetConfig() failed");
248 if (NumberOfChips
> 2)
249 fprintf(stderr
,"Target has more than one processor\n");
250 for (cnt
=0; cnt
< NumberOfRanges
; cnt
++)
252 switch(KnownMemory
[cnt
].Space
)
255 fprintf(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(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
))
309 error ("UDIDisconnect() failed in udi_close");
311 /* Do not try to close udi_session_id again, later in the program. */
315 #if defined (LOG_FILE)
316 if (ferror (log_file
))
317 printf ("Error writing log file.\n");
318 if (fclose (log_file
) != 0)
319 printf ("Error closing log file.\n");
322 printf_filtered (" Ending remote debugging\n");
325 /**************************************************************** UDI_ATACH */
326 /* Attach to a program that is already loaded and running
327 * Upon exiting the process's execution is stopped.
330 udi_attach (args
, from_tty
)
339 UDIBool HostEndian
= 0;
342 if (udi_session_id
< 0)
343 error ("UDI connection not opened yet, use the 'target udi' command.\n");
346 printf ("Attaching to remote program %s...\n", prog_name
);
349 From
.Space
= UDI29KSpecialRegs
;
351 if (err
= UDIRead(From
, &PC_adds
, Count
, Size
, &CountDone
, HostEndian
))
352 error ("UDIRead failed in udi_attach");
353 printf ("Remote process is now halted, pc1 = 0x%x.\n", PC_adds
);
355 /************************************************************* UDI_DETACH */
356 /* Terminate the open connection to the TIP process.
357 Use this when you want to detach and do something else
358 with your gdb. Leave remote process running (with no breakpoints set). */
360 udi_detach (args
,from_tty
)
365 remove_breakpoints(); /* Just in case there were any left in */
367 if (UDIDisconnect (udi_session_id
, UDIContinueSession
))
368 error ("UDIDisconnect() failed in udi_detach");
370 pop_target(); /* calls udi_close to do the real work */
373 printf ("Ending remote debugging\n");
377 /****************************************************************** UDI_RESUME
378 ** Tell the remote machine to resume. */
381 udi_resume (pid
, step
, sig
)
386 UDIStepType StepType
= UDIStepNatural
;
389 if (step
) /* step 1 instruction */
391 tip_error
= UDIStep (Steps
, StepType
, Range
);
395 fprintf (stderr
, "UDIStep() error = %d\n", tip_error
);
396 error ("failed in udi_resume");
400 error ("UDIExecute() failed in udi_resume");
403 /******************************************************************** UDI_WAIT
404 ** Wait until the remote machine stops, then return,
405 storing status in STATUS just as `wait' would. */
408 udi_wait (pid
, status
)
416 int old_timeout
= timeout
;
417 int old_immediate_quit
= immediate_quit
;
420 WSETEXIT ((*status
), 0);
422 /* wait for message to arrive. It should be:
423 If the target stops executing, udi_wait() should return.
425 timeout
= 0; /* Wait indefinetly for a message */
426 immediate_quit
= 1; /* Helps ability to QUIT */
431 MaxTime
= UDIWaitForever
;
432 UDIWait(MaxTime
, &PId
, &StopReason
);
433 QUIT
; /* Let user quit if they want */
435 switch (StopReason
& UDIGrossState
)
438 if (UDIGetStdout (sbuf
, (UDISizeT
)SBUF_MAX
, &CountDone
))
439 /* This is said to happen if the program tries to output
440 a whole bunch of output (more than SBUF_MAX, I would
441 guess). It doesn't seem to happen with the simulator. */
442 warning ("UDIGetStdout() failed in udi_wait");
443 fwrite (sbuf
, 1, CountDone
, stdout
);
447 UDIGetStderr (sbuf
, (UDISizeT
)SBUF_MAX
, &CountDone
);
448 fwrite (sbuf
, 1, CountDone
, stderr
);
462 } while (i
< SBUF_MAX
&& ch
!= '\n');
463 UDIPutStdin (sbuf
, (UDISizeT
)i
, &CountDone
);
468 /* In spite of the fact that we told UDIWait to wait forever, it will
469 return spuriously sometimes. */
478 switch (StopReason
& UDIGrossState
)
481 printf("Am290*0 received vector number %d\n", StopReason
>> 24);
483 switch (StopReason
>> 8)
485 case 0: /* Illegal opcode */
486 printf(" (break point)\n");
487 WSETSTOP ((*status
), SIGTRAP
);
489 case 1: /* Unaligned Access */
490 WSETSTOP ((*status
), SIGBUS
);
494 WSETSTOP ((*status
), SIGFPE
);
496 case 5: /* Protection Violation */
497 WSETSTOP ((*status
), SIGILL
);
501 case 8: /* User Instruction Mapping Miss */
502 case 9: /* User Data Mapping Miss */
503 case 10: /* Supervisor Instruction Mapping Miss */
504 case 11: /* Supervisor Data Mapping Miss */
505 WSETSTOP ((*status
), SIGSEGV
);
509 WSETSTOP ((*status
), SIGILL
);
512 WSETSTOP ((*status
), SIGALRM
);
515 WSETSTOP ((*status
), SIGTRAP
);
520 case 19: /* INTR3/Internal */
523 WSETSTOP ((*status
), SIGINT
);
525 case 22: /* Floating-Point Exception */
526 WSETSTOP ((*status
), SIGILL
);
528 case 77: /* assert 77 */
529 WSETSTOP ((*status
), SIGTRAP
);
532 WSETEXIT ((*status
), 0);
535 case UDINotExecuting
:
536 WSETSTOP ((*status
), SIGTERM
);
539 WSETSTOP ((*status
), SIGTSTP
);
542 WSETSTOP ((*status
), SIGURG
);
546 WSETSTOP ((*status
), SIGTRAP
);
549 WSETSTOP ((*status
), SIGSTOP
);
552 WSETSTOP ((*status
), SIGKILL
);
556 WSETEXIT ((*status
), 0);
559 timeout
= old_timeout
; /* Restore original timeout value */
560 immediate_quit
= old_immediate_quit
;
565 /* Handy for debugging */
573 UDIBool HostEndian
= 0;
576 unsigned long myregs
[256];
579 From
.Space
= UDI29KPC
;
581 To
= (UDIUInt32
*)pc
;
584 err
= UDIRead(From
, To
, Count
, Size
, &CountDone
, HostEndian
);
586 printf ("err = %d, CountDone = %d, pc[0] = 0x%x, pc[1] = 0x%x\n",
587 err
, CountDone
, pc
[0], pc
[1]);
589 udi_fetch_registers(-1);
591 printf("other pc1 = 0x%x, pc0 = 0x%x\n", *(int *)®isters
[4 * PC_REGNUM
],
592 *(int *)®isters
[4 * NPC_REGNUM
]);
594 /* Now, read all the registers globally */
596 From
.Space
= UDI29KGlobalRegs
;
598 err
= UDIRead(From
, myregs
, 256, 4, &CountDone
, HostEndian
);
600 printf ("err = %d, CountDone = %d\n", err
, CountDone
);
604 for (i
= 0; i
< 256; i
+= 2)
605 printf("%d:\t%#10x\t%11d\t%#10x\t%11d\n", i
, myregs
[i
], myregs
[i
],
606 myregs
[i
+1], myregs
[i
+1]);
613 /********************************************************** UDI_FETCH_REGISTERS
614 * Read a remote register 'regno'.
615 * If regno==-1 then read all the registers.
618 udi_fetch_registers (regno
)
626 UDIBool HostEndian
= 0;
631 fetch_register(regno
);
637 From
.Space
= UDI29KGlobalRegs
;
639 To
= (UDIUInt32
*)®isters
[4 * GR1_REGNUM
];
641 if (err
= UDIRead(From
, To
, Count
, Size
, &CountDone
, HostEndian
))
642 error("UDIRead() failed in udi_fetch_registers");
644 register_valid
[GR1_REGNUM
] = 1;
646 #if defined(GR64_REGNUM) /* Read gr64-127 */
648 /* Global Registers gr64-gr95 */
650 From
.Space
= UDI29KGlobalRegs
;
652 To
= (UDIUInt32
*)®isters
[4 * GR64_REGNUM
];
654 if (err
= UDIRead(From
, To
, Count
, Size
, &CountDone
, HostEndian
))
655 error("UDIRead() failed in udi_fetch_registers");
657 for (i
= GR64_REGNUM
; i
< GR64_REGNUM
+ 32; i
++)
658 register_valid
[i
] = 1;
660 #endif /* GR64_REGNUM */
662 /* Global Registers gr96-gr127 */
664 From
.Space
= UDI29KGlobalRegs
;
666 To
= (UDIUInt32
*)®isters
[4 * GR96_REGNUM
];
668 if (err
= UDIRead(From
, To
, Count
, Size
, &CountDone
, HostEndian
))
669 error("UDIRead() failed in udi_fetch_registers");
671 for (i
= GR96_REGNUM
; i
< GR96_REGNUM
+ 32; i
++)
672 register_valid
[i
] = 1;
674 /* Local Registers */
676 From
.Space
= UDI29KLocalRegs
;
678 To
= (UDIUInt32
*)®isters
[4 * LR0_REGNUM
];
680 if (err
= UDIRead(From
, To
, Count
, Size
, &CountDone
, HostEndian
))
681 error("UDIRead() failed in udi_fetch_registers");
683 for (i
= LR0_REGNUM
; i
< LR0_REGNUM
+ 128; i
++)
684 register_valid
[i
] = 1;
686 /* Protected Special Registers */
688 From
.Space
= UDI29KSpecialRegs
;
690 To
= (UDIUInt32
*)®isters
[4 * SR_REGNUM(0)];
692 if (err
= UDIRead(From
, To
, Count
, Size
, &CountDone
, HostEndian
))
693 error("UDIRead() failed in udi_fetch_registers");
695 for (i
= SR_REGNUM(0); i
< SR_REGNUM(0) + 15; i
++)
696 register_valid
[i
] = 1;
698 if (USE_SHADOW_PC
) { /* Let regno_to_srnum() handle the register number */
699 fetch_register(NPC_REGNUM
);
700 fetch_register(PC_REGNUM
);
701 fetch_register(PC2_REGNUM
);
703 /* Unprotected Special Registers sr128-sr135 */
705 From
.Space
= UDI29KSpecialRegs
;
707 To
= (UDIUInt32
*)®isters
[4 * SR_REGNUM(128)];
709 if (err
= UDIRead(From
, To
, Count
, Size
, &CountDone
, HostEndian
))
710 error("UDIRead() failed in udi_fetch_registers");
712 for (i
= SR_REGNUM(128); i
< SR_REGNUM(128) + 135-128+1; i
++)
713 register_valid
[i
] = 1;
718 printf("Fetching all registers\n");
719 printf("Fetching PC0 = 0x%x, PC1 = 0x%x, PC2 = 0x%x\n",
720 read_register(NPC_REGNUM
), read_register(PC_REGNUM
),
721 read_register(PC2_REGNUM
));
724 /* There doesn't seem to be any way to get these. */
727 supply_register (FPE_REGNUM
, (char *) &val
);
728 supply_register (INTE_REGNUM
, (char *) &val
);
729 supply_register (FPS_REGNUM
, (char *) &val
);
730 supply_register (EXO_REGNUM
, (char *) &val
);
735 /********************************************************* UDI_STORE_REGISTERS
736 ** Store register regno into the target.
737 * If regno==-1 then store all the registers.
741 udi_store_registers (regno
)
749 UDIBool HostEndian
= 0;
753 store_register(regno
);
759 printf("Storing all registers\n");
760 printf("PC0 = 0x%x, PC1 = 0x%x, PC2 = 0x%x\n", read_register(NPC_REGNUM
),
761 read_register(PC_REGNUM
), read_register(PC2_REGNUM
));
766 From
= (UDIUInt32
*)®isters
[4 * GR1_REGNUM
];
767 To
.Space
= UDI29KGlobalRegs
;
770 if(UDIWrite(From
, To
, Count
, Size
, &CountDone
, HostEndian
))
771 error("UDIWrite() failed in udi_store_regisetrs");
773 #if defined(GR64_REGNUM)
775 /* Global registers gr64-gr95 */
777 From
= (UDIUInt32
*)®isters
[4 * GR64_REGNUM
];
778 To
.Space
= UDI29KGlobalRegs
;
781 if(UDIWrite(From
, To
, Count
, Size
, &CountDone
, HostEndian
))
782 error("UDIWrite() failed in udi_store_regisetrs");
784 #endif /* GR64_REGNUM */
786 /* Global registers gr96-gr127 */
788 From
= (UDIUInt32
*)®isters
[4 * GR96_REGNUM
];
789 To
.Space
= UDI29KGlobalRegs
;
792 if(UDIWrite(From
, To
, Count
, Size
, &CountDone
, HostEndian
))
793 error("UDIWrite() failed in udi_store_regisetrs");
795 /* Local Registers */
797 From
= (UDIUInt32
*)®isters
[4 * LR0_REGNUM
];
798 To
.Space
= UDI29KLocalRegs
;
801 if(UDIWrite(From
, To
, Count
, Size
, &CountDone
, HostEndian
))
802 error("UDIWrite() failed in udi_store_regisetrs");
805 /* Protected Special Registers */ /* VAB through TMR */
807 From
= (UDIUInt32
*)®isters
[4 * SR_REGNUM(0)];
808 To
.Space
= UDI29KSpecialRegs
;
811 if(UDIWrite(From
, To
, Count
, Size
, &CountDone
, HostEndian
))
812 error("UDIWrite() failed in udi_store_regisetrs");
814 /* PC0, PC1, PC2 possibly as shadow registers */
816 From
= (UDIUInt32
*)®isters
[4 * SR_REGNUM(10)];
817 To
.Space
= UDI29KSpecialRegs
;
820 To
.Offset
= 20; /* SPC0 */
822 To
.Offset
= 10; /* PC0 */
823 if(UDIWrite(From
, To
, Count
, Size
, &CountDone
, HostEndian
))
824 error("UDIWrite() failed in udi_store_regisetrs");
826 /* PC1 via UDI29KPC */
828 From
= (UDIUInt32
*)®isters
[4 * PC_REGNUM
];
830 To
.Offset
= 0; /* PC1 */
832 if (UDIWrite (From
, To
, Count
, Size
, &CountDone
, HostEndian
))
833 error ("UDIWrite() failed in udi_store_regisetrs");
837 From
= (UDIUInt32
*)®isters
[4 * SR_REGNUM(13)];
838 To
.Space
= UDI29KSpecialRegs
;
841 if(UDIWrite(From
, To
, Count
, Size
, &CountDone
, HostEndian
))
842 error("UDIWrite() failed in udi_store_regisetrs");
844 /* Unprotected Special Registers */
846 From
= (UDIUInt32
*)®isters
[4 * SR_REGNUM(128)];
847 To
.Space
= UDI29KSpecialRegs
;
850 if(UDIWrite(From
, To
, Count
, Size
, &CountDone
, HostEndian
))
851 error("UDIWrite() failed in udi_store_regisetrs");
853 registers_changed ();
856 /****************************************************** UDI_PREPARE_TO_STORE */
857 /* Get ready to modify the registers array. On machines which store
858 individual registers, this doesn't need to do anything. On machines
859 which store all the registers in one fell swoop, this makes sure
860 that registers contains all the registers from the program being
864 udi_prepare_to_store ()
866 /* Do nothing, since we can store individual regs */
869 /********************************************************** TRANSLATE_ADDR */
874 #if defined(ULTRA3) && defined(KERNEL_DEBUGGING)
875 /* Check for a virtual address in the kernel */
876 /* Assume physical address of ublock is in paddr_u register */
877 /* FIXME: doesn't work for user virtual addresses */
878 if (addr
>= UVADDR
) {
879 /* PADDR_U register holds the physical address of the ublock */
880 CORE_ADDR i
= (CORE_ADDR
)read_register(PADDR_U_REGNUM
);
881 return(i
+ addr
- (CORE_ADDR
)UVADDR
);
889 /************************************************* UDI_XFER_INFERIOR_MEMORY */
890 /* FIXME! Merge these two. */
892 udi_xfer_inferior_memory (memaddr
, myaddr
, len
, write
)
899 memaddr
= translate_addr(memaddr
);
902 return udi_write_inferior_memory (memaddr
, myaddr
, len
);
904 return udi_read_inferior_memory (memaddr
, myaddr
, len
);
907 /********************************************************** UDI_FILES_INFO */
911 printf ("\tAttached to UDI socket to %s and running program %s.\n",
912 udi_config_id
, prog_name
);
915 /**************************************************** UDI_INSERT_BREAKPOINT */
917 udi_insert_breakpoint (addr
, contents_cache
)
919 char *contents_cache
;
924 for (cnt
= 0; cnt
< BKPT_TABLE_SIZE
; cnt
++)
925 if (bkpt_table
[cnt
].Type
== 0) /* Find first free slot */
928 if(cnt
>= BKPT_TABLE_SIZE
)
929 error("Too many breakpoints set");
931 bkpt_table
[cnt
].Addr
.Offset
= addr
;
932 bkpt_table
[cnt
].Addr
.Space
= UDI29KIRAMSpace
;
933 bkpt_table
[cnt
].PassCount
= 1;
934 bkpt_table
[cnt
].Type
= UDIBreakFlagExecute
;
936 err
= UDISetBreakpoint(bkpt_table
[cnt
].Addr
,
937 bkpt_table
[cnt
].PassCount
,
938 bkpt_table
[cnt
].Type
,
939 &bkpt_table
[cnt
].BreakId
);
941 if (err
== 0) return 0; /* Success */
943 bkpt_table
[cnt
].Type
= 0;
944 error("UDISetBreakpoint returned error code %d\n", err
);
947 /**************************************************** UDI_REMOVE_BREAKPOINT */
949 udi_remove_breakpoint (addr
, contents_cache
)
951 char *contents_cache
;
956 for (cnt
= 0; cnt
< BKPT_TABLE_SIZE
; cnt
++)
957 if (bkpt_table
[cnt
].Addr
.Offset
== addr
) /* Find matching breakpoint */
960 if(cnt
>= BKPT_TABLE_SIZE
)
961 error("Can't find breakpoint in table");
963 bkpt_table
[cnt
].Type
= 0;
965 err
= UDIClearBreakpoint(bkpt_table
[cnt
].BreakId
);
966 if (err
== 0) return 0; /* Success */
968 error("UDIClearBreakpoint returned error code %d\n", err
);
972 udi_kill(arg
,from_tty
)
979 UDIStop does not really work as advertised. It causes the TIP to close it's
980 connection, which usually results in GDB dying with a SIGPIPE. For now, we
981 just invoke udi_close, which seems to get things right.
989 printf("Target has been stopped.");
997 Load a program into the target. Args are: `program {options}'. The options
998 are used to control loading of the program, and are NOT passed onto the
999 loaded code as arguments. (You need to use the `run' command to do that.)
1002 -ms %d Set mem stack size to %d
1003 -rs %d Set regular stack size to %d
1004 -i send init info (default)
1005 -noi don't send init info
1006 -[tT] Load Text section
1007 -[dD] Load Data section
1008 -[bB] Load BSS section
1009 -[lL] Load Lit section
1013 download(load_arg_string
, from_tty
)
1014 char *load_arg_string
;
1017 #define DEFAULT_MEM_STACK_SIZE 0x6000
1018 #define DEFAULT_REG_STACK_SIZE 0x2000
1025 int load_text
= 1, load_data
= 1, load_bss
= 1, load_lit
= 1;
1027 address_ranges
[0].Space
= UDI29KIRAMSpace
;
1028 address_ranges
[0].Offset
= 0xffffffff;
1029 address_ranges
[0].Size
= 0;
1031 address_ranges
[1].Space
= UDI29KDRAMSpace
;
1032 address_ranges
[1].Offset
= 0xffffffff;
1033 address_ranges
[1].Size
= 0;
1035 stack_sizes
[0] = DEFAULT_REG_STACK_SIZE
;
1036 stack_sizes
[1] = DEFAULT_MEM_STACK_SIZE
;
1040 filename
= strtok(load_arg_string
, " \t");
1042 error ("Must specify at least a file name with the load command");
1044 filename
= tilde_expand (filename
);
1045 make_cleanup (free
, filename
);
1047 while (token
= strtok (NULL
, " \t"))
1049 if (token
[0] == '-')
1053 if (STREQ (token
, "ms"))
1054 stack_sizes
[1] = atol (strtok (NULL
, " \t"));
1055 else if (STREQ (token
, "rs"))
1056 stack_sizes
[0] = atol (strtok (NULL
, " \t"));
1059 load_text
= load_data
= load_bss
= load_lit
= 0;
1082 error ("Unknown UDI load option -%s", token
-1);
1089 pbfd
= bfd_openr (filename
, gnutarget
);
1092 perror_with_name (filename
);
1094 make_cleanup (bfd_close
, pbfd
);
1099 if (!bfd_check_format (pbfd
, bfd_object
))
1100 error ("It doesn't seem to be an object file");
1102 for (section
= pbfd
->sections
; section
; section
= section
->next
)
1104 if (bfd_get_section_flags (pbfd
, section
) & SEC_ALLOC
)
1108 unsigned long section_size
, section_end
;
1109 const char *section_name
;
1111 section_name
= bfd_get_section_name (pbfd
, section
);
1112 if (STREQ (section_name
, ".text") && !load_text
)
1114 else if (STREQ (section_name
, ".data") && !load_data
)
1116 else if (STREQ (section_name
, ".bss") && !load_bss
)
1118 else if (STREQ (section_name
, ".lit") && !load_lit
)
1121 To
.Offset
= bfd_get_section_vma (pbfd
, section
);
1122 section_size
= bfd_section_size (pbfd
, section
);
1123 section_end
= To
.Offset
+ section_size
;
1125 if (section_size
== 0)
1126 /* This is needed at least in the BSS case, where the code
1127 below starts writing before it even checks the size. */
1130 printf("[Loading section %s at %x (%d bytes)]\n",
1135 if (bfd_get_section_flags (pbfd
, section
) & SEC_CODE
)
1137 To
.Space
= UDI29KIRAMSpace
;
1139 address_ranges
[0].Offset
= min (address_ranges
[0].Offset
,
1141 address_ranges
[0].Size
= max (address_ranges
[0].Size
,
1143 - address_ranges
[0].Offset
);
1147 To
.Space
= UDI29KDRAMSpace
;
1149 address_ranges
[1].Offset
= min (address_ranges
[1].Offset
,
1151 address_ranges
[1].Size
= max (address_ranges
[1].Size
,
1153 - address_ranges
[1].Offset
);
1156 if (bfd_get_section_flags (pbfd
, section
) & SEC_LOAD
) /* Text, data or lit */
1162 while (section_size
> 0)
1166 Count
= min (section_size
, 1024);
1168 bfd_get_section_contents (pbfd
, section
, buffer
, fptr
,
1171 err
= UDIWrite ((UDIHostMemPtr
)buffer
, /* From */
1174 (UDISizeT
)1, /* Size */
1175 &Count
, /* CountDone */
1176 (UDIBool
)0); /* HostEndian */
1178 error ("UDIWrite failed, error = %d", err
);
1182 section_size
-= Count
;
1188 unsigned long zero
= 0;
1190 /* Write a zero byte at the vma */
1191 /* FIXME: Broken for sections of 1-3 bytes (we test for
1193 err
= UDIWrite ((UDIHostMemPtr
)&zero
, /* From */
1195 (UDICount
)1, /* Count */
1196 (UDISizeT
)4, /* Size */
1197 &Count
, /* CountDone */
1198 (UDIBool
)0); /* HostEndian */
1200 error ("UDIWrite failed, error = %d", err
);
1205 /* Now, duplicate it for the length of the BSS */
1206 err
= UDICopy (From
, /* From */
1208 (UDICount
)(section_size
/4 - 1), /* Count */
1209 (UDISizeT
)4, /* Size */
1210 &Count
, /* CountDone */
1211 (UDIBool
)1); /* Direction */
1217 xerr
= UDIGetErrorMsg(err
, 100, message
, &Count
);
1219 fprintf (stderr
, "Error is %s\n", message
);
1221 fprintf (stderr
, "xerr is %d\n", xerr
);
1222 error ("UDICopy failed, error = %d", err
);
1229 entry
.Space
= UDI29KIRAMSpace
;
1230 entry
.Offset
= bfd_get_start_address (pbfd
);
1235 /* User interface to download an image into the remote target. See download()
1236 * for details on args.
1240 udi_load(args
, from_tty
)
1244 download (args
, from_tty
);
1246 symbol_file_add (strtok (args
, " \t"), from_tty
, 0, 0, 0, 0);
1249 /*************************************************** UDI_WRITE_INFERIOR_MEMORY
1250 ** Copy LEN bytes of data from debugger memory at MYADDR
1251 to inferior's memory at MEMADDR. Returns number of bytes written. */
1253 udi_write_inferior_memory (memaddr
, myaddr
, len
)
1263 UDICount CountDone
= 0;
1264 UDIBool HostEndian
= 0;
1266 To
.Space
= udi_memory_space(memaddr
);
1267 From
= (UDIUInt32
*)myaddr
;
1269 while (nwritten
< len
)
1270 { Count
= len
- nwritten
;
1271 if (Count
> MAXDATA
) Count
= MAXDATA
;
1272 To
.Offset
= memaddr
+ nwritten
;
1273 if(UDIWrite(From
, To
, Count
, Size
, &CountDone
, HostEndian
))
1274 { error("UDIWrite() failed in udi_write_inferrior_memory");
1278 { nwritten
+= CountDone
;
1285 /**************************************************** UDI_READ_INFERIOR_MEMORY
1286 ** Read LEN bytes from inferior memory at MEMADDR. Put the result
1287 at debugger address MYADDR. Returns number of bytes read. */
1289 udi_read_inferior_memory(memaddr
, myaddr
, len
)
1299 UDICount CountDone
= 0;
1300 UDIBool HostEndian
= 0;
1303 From
.Space
= udi_memory_space(memaddr
);
1304 To
= (UDIUInt32
*)myaddr
;
1307 { Count
= len
- nread
;
1308 if (Count
> MAXDATA
) Count
= MAXDATA
;
1309 From
.Offset
= memaddr
+ nread
;
1310 if(err
= UDIRead(From
, To
, Count
, Size
, &CountDone
, HostEndian
))
1311 { error("UDIRead() failed in udi_read_inferrior_memory");
1315 { nread
+= CountDone
;
1322 /********************************************************************* WARNING
1327 error ("ERROR while loading program into remote TIP: $d\n", num
);
1331 /*****************************************************************************/
1332 /* Fetch a single register indicatated by 'regno'.
1333 * Returns 0/-1 on success/failure.
1336 fetch_register (regno
)
1344 UDIBool HostEndian
= 0;
1348 if (regno
== GR1_REGNUM
)
1350 From
.Space
= UDI29KGlobalRegs
;
1353 else if (regno
>= GR96_REGNUM
&& regno
< GR96_REGNUM
+ 32)
1355 From
.Space
= UDI29KGlobalRegs
;
1356 From
.Offset
= (regno
- GR96_REGNUM
) + 96;;
1359 #if defined(GR64_REGNUM)
1361 else if (regno
>= GR64_REGNUM
&& regno
< GR64_REGNUM
+ 32 )
1363 From
.Space
= UDI29KGlobalRegs
;
1364 From
.Offset
= (regno
- GR64_REGNUM
) + 64;
1367 #endif /* GR64_REGNUM */
1369 else if (regno
>= LR0_REGNUM
&& regno
< LR0_REGNUM
+ 128)
1371 From
.Space
= UDI29KLocalRegs
;
1372 From
.Offset
= (regno
- LR0_REGNUM
);
1374 else if (regno
>=FPE_REGNUM
&& regno
<=EXO_REGNUM
)
1377 supply_register(160 + (regno
- FPE_REGNUM
),(char *) &val
);
1378 return; /* Pretend Success */
1382 From
.Space
= UDI29KSpecialRegs
;
1383 From
.Offset
= regnum_to_srnum(regno
);
1386 if (err
= UDIRead(From
, &To
, Count
, Size
, &CountDone
, HostEndian
))
1387 error("UDIRead() failed in udi_fetch_registers");
1389 supply_register(regno
, (char *) &To
);
1392 printf("Fetching register %s = 0x%x\n", reg_names
[regno
], To
);
1394 /*****************************************************************************/
1395 /* Store a single register indicated by 'regno'.
1396 * Returns 0/-1 on success/failure.
1399 store_register (regno
)
1408 UDIBool HostEndian
= 0;
1410 From
= read_register (regno
); /* get data value */
1413 printf("Storing register %s = 0x%x\n", reg_names
[regno
], From
);
1415 if (regno
== GR1_REGNUM
)
1417 To
.Space
= UDI29KGlobalRegs
;
1419 result
= UDIWrite(&From
, To
, Count
, Size
, &CountDone
, HostEndian
);
1420 /* Setting GR1 changes the numbers of all the locals, so invalidate the
1421 * register cache. Do this *after* calling read_register, because we want
1422 * read_register to return the value that write_register has just stuffed
1423 * into the registers array, not the value of the register fetched from
1426 registers_changed ();
1428 #if defined(GR64_REGNUM)
1429 else if (regno
>= GR64_REGNUM
&& regno
< GR64_REGNUM
+ 32 )
1431 To
.Space
= UDI29KGlobalRegs
;
1432 To
.Offset
= (regno
- GR64_REGNUM
) + 64;
1433 result
= UDIWrite(&From
, To
, Count
, Size
, &CountDone
, HostEndian
);
1435 #endif /* GR64_REGNUM */
1436 else if (regno
>= GR96_REGNUM
&& regno
< GR96_REGNUM
+ 32)
1438 To
.Space
= UDI29KGlobalRegs
;
1439 To
.Offset
= (regno
- GR96_REGNUM
) + 96;
1440 result
= UDIWrite(&From
, To
, Count
, Size
, &CountDone
, HostEndian
);
1442 else if (regno
>= LR0_REGNUM
&& regno
< LR0_REGNUM
+ 128)
1444 To
.Space
= UDI29KLocalRegs
;
1445 To
.Offset
= (regno
- LR0_REGNUM
);
1446 result
= UDIWrite(&From
, To
, Count
, Size
, &CountDone
, HostEndian
);
1448 else if (regno
>= FPE_REGNUM
&& regno
<= EXO_REGNUM
)
1449 return 0; /* Pretend Success */
1450 else if (regno
== PC_REGNUM
)
1452 /* PC1 via UDI29KPC */
1454 To
.Space
= UDI29KPC
;
1455 To
.Offset
= 0; /* PC1 */
1456 result
= UDIWrite (&From
, To
, Count
, Size
, &CountDone
, HostEndian
);
1458 /* Writing to this loc actually changes the values of pc0 & pc1 */
1460 register_valid
[PC_REGNUM
] = 0; /* pc1 */
1461 register_valid
[NPC_REGNUM
] = 0; /* pc0 */
1463 else /* An unprotected or protected special register */
1465 To
.Space
= UDI29KSpecialRegs
;
1466 To
.Offset
= regnum_to_srnum(regno
);
1467 result
= UDIWrite(&From
, To
, Count
, Size
, &CountDone
, HostEndian
);
1471 error("UDIWrite() failed in store_registers");
1475 /********************************************************** REGNUM_TO_SRNUM */
1477 * Convert a gdb special register number to a 29000 special register number.
1480 regnum_to_srnum(regno
)
1484 case VAB_REGNUM
: return(0);
1485 case OPS_REGNUM
: return(1);
1486 case CPS_REGNUM
: return(2);
1487 case CFG_REGNUM
: return(3);
1488 case CHA_REGNUM
: return(4);
1489 case CHD_REGNUM
: return(5);
1490 case CHC_REGNUM
: return(6);
1491 case RBP_REGNUM
: return(7);
1492 case TMC_REGNUM
: return(8);
1493 case TMR_REGNUM
: return(9);
1494 case NPC_REGNUM
: return(USE_SHADOW_PC
? (20) : (10));
1495 case PC_REGNUM
: return(USE_SHADOW_PC
? (21) : (11));
1496 case PC2_REGNUM
: return(USE_SHADOW_PC
? (22) : (12));
1497 case MMU_REGNUM
: return(13);
1498 case LRU_REGNUM
: return(14);
1499 case IPC_REGNUM
: return(128);
1500 case IPA_REGNUM
: return(129);
1501 case IPB_REGNUM
: return(130);
1502 case Q_REGNUM
: return(131);
1503 case ALU_REGNUM
: return(132);
1504 case BP_REGNUM
: return(133);
1505 case FC_REGNUM
: return(134);
1506 case CR_REGNUM
: return(135);
1507 case FPE_REGNUM
: return(160);
1508 case INTE_REGNUM
: return(161);
1509 case FPS_REGNUM
: return(162);
1510 case EXO_REGNUM
:return(164);
1512 return(255); /* Failure ? */
1515 /****************************************************************************/
1517 * Determine the Target memory space qualifier based on the addr.
1518 * FIXME: Can't distinguis I_ROM/D_ROM.
1519 * FIXME: Doesn't know anything about I_CACHE/D_CACHE.
1522 udi_memory_space(addr
)
1525 UDIUInt32 tstart
= IMemStart
;
1526 UDIUInt32 tend
= tstart
+ IMemSize
;
1527 UDIUInt32 dstart
= DMemStart
;
1528 UDIUInt32 dend
= tstart
+ DMemSize
;
1529 UDIUInt32 rstart
= RMemStart
;
1530 UDIUInt32 rend
= tstart
+ RMemSize
;
1532 if (((UDIUInt32
)addr
>= tstart
) && ((UDIUInt32
)addr
< tend
)) {
1533 return UDI29KIRAMSpace
;
1534 } else if (((UDIUInt32
)addr
>= dstart
) && ((UDIUInt32
)addr
< dend
)) {
1535 return UDI29KDRAMSpace
;
1536 } else if (((UDIUInt32
)addr
>= rstart
) && ((UDIUInt32
)addr
< rend
)) {
1537 /* FIXME: how do we determine between D_ROM and I_ROM */
1538 return UDI29KIROMSpace
;
1539 } else /* FIXME: what do me do now? */
1540 return UDI29KDRAMSpace
; /* Hmmm! */
1542 /*********************************************************************** STUBS
1545 void convert16() {;}
1546 void convert32() {;}
1547 FILE* EchoFile
= 0; /* used for debugging */
1548 int QuietMode
= 0; /* used for debugging */
1550 #ifdef NO_HIF_SUPPORT
1554 return(0); /* Emulate a failure */
1558 /* Target_ops vector. Not static because there does not seem to be
1559 any portable way to do a forward declaration of a static variable.
1560 The RS/6000 doesn't like "extern" followed by "static"; SunOS
1561 /bin/cc doesn't like "static" twice. */
1563 struct target_ops udi_ops
= {
1565 "Remote UDI connected TIP",
1566 "Remote debug an AMD 29k using UDI socket connection to TIP process.\n\
1568 `configuration-id AF_INET hostname port-number'\n\
1569 To connect via the network, where hostname and port-number specify the\n\
1570 host and port where you can connect via UDI.\n\
1571 configuration-id is unused.\n\
1573 `configuration-id AF_UNIX socket-name tip-program'\n\
1574 To connect using a local connection to the \"tip.exe\" program which is\n\
1575 supplied by AMD. If socket-name specifies an AF_UNIX socket then the\n\
1576 tip program must already be started; connect to it using that socket.\n\
1577 If not, start up tip-program, which should be the name of the tip\n\
1578 program. If appropriate, the PATH environment variable is searched.\n\
1579 configuration-id is unused.\n\
1581 `configuration-id'\n\
1582 Look up the configuration in ./udi_soc or /etc/udi_soc, which\n\
1583 are files containing lines in the above formats. configuration-id is\n\
1584 used to pick which line of the file to use.",
1591 udi_fetch_registers
,
1592 udi_store_registers
,
1593 udi_prepare_to_store
,
1594 udi_xfer_inferior_memory
,
1596 udi_insert_breakpoint
,
1597 udi_remove_breakpoint
,
1598 0, /* termial_init */
1599 0, /* terminal_inferior */
1600 0, /* terminal_ours_for_output */
1601 0, /* terminal_ours */
1602 0, /* terminal_info */
1603 udi_kill
, /* FIXME, kill */
1605 0, /* lookup_symbol */
1606 udi_create_inferior
,
1607 udi_mourn
, /* mourn_inferior FIXME */
1609 0, /* notice_signals */
1612 1, /* has_all_memory */
1615 1, /* has_registers */
1616 1, /* has_execution */
1618 0, /* sections_end */
1619 OPS_MAGIC
, /* Always the last thing */
1623 _initialize_remote_udi ()
1625 add_target (&udi_ops
);