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;
340 if (udi_session_id
< 0)
341 error ("UDI connection not opened yet, use the 'target udi' command.\n");
344 printf_unfiltered ("Attaching to remote program %s...\n", prog_name
);
347 From
.Space
= UDI29KSpecialRegs
;
349 if (err
= UDIRead(From
, &PC_adds
, Count
, Size
, &CountDone
, HostEndian
))
350 error ("UDIRead failed in udi_attach");
351 printf_unfiltered ("Remote process is now halted, pc1 = 0x%x.\n", PC_adds
);
353 /************************************************************* UDI_DETACH */
354 /* Terminate the open connection to the TIP process.
355 Use this when you want to detach and do something else
356 with your gdb. Leave remote process running (with no breakpoints set). */
358 udi_detach (args
,from_tty
)
363 remove_breakpoints(); /* Just in case there were any left in */
365 if (UDIDisconnect (udi_session_id
, UDIContinueSession
))
366 error ("UDIDisconnect() failed in udi_detach");
368 /* calls udi_close to do the real work (which looks like it calls
369 UDIDisconnect with UDITerminateSession, FIXME). */
372 /* FIXME, message too similar to what udi_close prints. */
374 printf_unfiltered ("Ending remote debugging\n");
378 /****************************************************************** UDI_RESUME
379 ** Tell the remote machine to resume. */
382 udi_resume (pid
, step
, sig
)
384 enum target_signal sig
;
388 UDIStepType StepType
= UDIStepNatural
;
391 if (step
) /* step 1 instruction */
393 tip_error
= UDIStep (Steps
, StepType
, Range
);
397 fprintf_unfiltered (gdb_stderr
, "UDIStep() error = %d\n", tip_error
);
398 error ("failed in udi_resume");
402 error ("UDIExecute() failed in udi_resume");
405 /******************************************************************** UDI_WAIT
406 ** Wait until the remote machine stops, then return,
407 storing status in STATUS just as `wait' would. */
410 udi_wait (pid
, status
)
412 struct target_waitstatus
*status
;
418 int old_timeout
= timeout
;
419 int old_immediate_quit
= immediate_quit
;
422 status
->kind
= TARGET_WAITKIND_EXITED
;
423 status
->value
.integer
= 0;
425 /* wait for message to arrive. It should be:
426 If the target stops executing, udi_wait() should return.
428 timeout
= 0; /* Wait indefinetly for a message */
429 immediate_quit
= 1; /* Helps ability to QUIT */
434 MaxTime
= UDIWaitForever
;
435 UDIWait(MaxTime
, &PId
, &StopReason
);
436 QUIT
; /* Let user quit if they want */
438 switch (StopReason
& UDIGrossState
)
441 if (UDIGetStdout (sbuf
, (UDISizeT
)SBUF_MAX
, &CountDone
))
442 /* This is said to happen if the program tries to output
443 a whole bunch of output (more than SBUF_MAX, I would
444 guess). It doesn't seem to happen with the simulator. */
445 warning ("UDIGetStdout() failed in udi_wait");
446 fwrite (sbuf
, 1, CountDone
, gdb_stdout
);
447 gdb_flush(gdb_stdout
);
451 UDIGetStderr (sbuf
, (UDISizeT
)SBUF_MAX
, &CountDone
);
452 fwrite (sbuf
, 1, CountDone
, gdb_stderr
);
453 gdb_flush(gdb_stderr
);
466 } while (i
< SBUF_MAX
&& ch
!= '\n');
467 UDIPutStdin (sbuf
, (UDISizeT
)i
, &CountDone
);
472 /* In spite of the fact that we told UDIWait to wait forever, it will
473 return spuriously sometimes. */
482 switch (StopReason
& UDIGrossState
)
485 printf_unfiltered("Am290*0 received vector number %d\n", StopReason
>> 24);
487 switch (StopReason
>> 8)
489 case 0: /* Illegal opcode */
490 printf_unfiltered(" (break point)\n");
491 status
->kind
= TARGET_WAITKIND_STOPPED
;
492 status
->value
.sig
= TARGET_SIGNAL_TRAP
;
494 case 1: /* Unaligned Access */
495 status
->kind
= TARGET_WAITKIND_STOPPED
;
496 status
->value
.sig
= TARGET_SIGNAL_BUS
;
500 status
->kind
= TARGET_WAITKIND_STOPPED
;
501 status
->value
.sig
= TARGET_SIGNAL_FPE
;
503 case 5: /* Protection Violation */
504 status
->kind
= TARGET_WAITKIND_STOPPED
;
505 /* Why not SEGV? What is a Protection Violation? */
506 status
->value
.sig
= TARGET_SIGNAL_ILL
;
510 case 8: /* User Instruction Mapping Miss */
511 case 9: /* User Data Mapping Miss */
512 case 10: /* Supervisor Instruction Mapping Miss */
513 case 11: /* Supervisor Data Mapping Miss */
514 status
->kind
= TARGET_WAITKIND_STOPPED
;
515 status
->value
.sig
= TARGET_SIGNAL_SEGV
;
519 status
->kind
= TARGET_WAITKIND_STOPPED
;
520 status
->value
.sig
= TARGET_SIGNAL_ILL
;
523 status
->kind
= TARGET_WAITKIND_STOPPED
;
524 status
->value
.sig
= TARGET_SIGNAL_ALRM
;
527 status
->kind
= TARGET_WAITKIND_STOPPED
;
528 status
->value
.sig
= TARGET_SIGNAL_TRAP
;
533 case 19: /* INTR3/Internal */
536 status
->kind
= TARGET_WAITKIND_STOPPED
;
537 status
->value
.sig
= TARGET_SIGNAL_INT
;
539 case 22: /* Floating-Point Exception */
540 status
->kind
= TARGET_WAITKIND_STOPPED
;
542 status
->value
.sig
= TARGET_SIGNAL_ILL
;
544 case 77: /* assert 77 */
545 status
->kind
= TARGET_WAITKIND_STOPPED
;
546 status
->value
.sig
= TARGET_SIGNAL_TRAP
;
549 status
->kind
= TARGET_WAITKIND_EXITED
;
550 status
->value
.integer
= 0;
553 case UDINotExecuting
:
554 status
->kind
= TARGET_WAITKIND_STOPPED
;
555 status
->value
.sig
= TARGET_SIGNAL_TERM
;
558 status
->kind
= TARGET_WAITKIND_STOPPED
;
559 status
->value
.sig
= TARGET_SIGNAL_TSTP
;
562 status
->kind
= TARGET_WAITKIND_STOPPED
;
563 status
->value
.sig
= TARGET_SIGNAL_URG
;
567 status
->kind
= TARGET_WAITKIND_STOPPED
;
568 status
->value
.sig
= TARGET_SIGNAL_TRAP
;
571 status
->kind
= TARGET_WAITKIND_STOPPED
;
572 status
->value
.sig
= TARGET_SIGNAL_STOP
;
575 status
->kind
= TARGET_WAITKIND_STOPPED
;
576 status
->value
.sig
= TARGET_SIGNAL_KILL
;
580 status
->kind
= TARGET_WAITKIND_EXITED
;
581 status
->value
.integer
= 0;
584 timeout
= old_timeout
; /* Restore original timeout value */
585 immediate_quit
= old_immediate_quit
;
590 /* Handy for debugging */
598 UDIBool HostEndian
= 0;
601 unsigned long myregs
[256];
604 From
.Space
= UDI29KPC
;
606 To
= (UDIUInt32
*)pc
;
609 err
= UDIRead(From
, To
, Count
, Size
, &CountDone
, HostEndian
);
611 printf_unfiltered ("err = %d, CountDone = %d, pc[0] = 0x%x, pc[1] = 0x%x\n",
612 err
, CountDone
, pc
[0], pc
[1]);
614 udi_fetch_registers(-1);
616 printf_unfiltered("other pc1 = 0x%x, pc0 = 0x%x\n", *(int *)®isters
[4 * PC_REGNUM
],
617 *(int *)®isters
[4 * NPC_REGNUM
]);
619 /* Now, read all the registers globally */
621 From
.Space
= UDI29KGlobalRegs
;
623 err
= UDIRead(From
, myregs
, 256, 4, &CountDone
, HostEndian
);
625 printf ("err = %d, CountDone = %d\n", err
, CountDone
);
629 for (i
= 0; i
< 256; i
+= 2)
630 printf("%d:\t%#10x\t%11d\t%#10x\t%11d\n", i
, myregs
[i
], myregs
[i
],
631 myregs
[i
+1], myregs
[i
+1]);
638 /********************************************************** UDI_FETCH_REGISTERS
639 * Read a remote register 'regno'.
640 * If regno==-1 then read all the registers.
643 udi_fetch_registers (regno
)
651 UDIBool HostEndian
= 0;
656 fetch_register(regno
);
662 From
.Space
= UDI29KGlobalRegs
;
664 To
= (UDIUInt32
*)®isters
[4 * GR1_REGNUM
];
666 if (err
= UDIRead(From
, To
, Count
, Size
, &CountDone
, HostEndian
))
667 error("UDIRead() failed in udi_fetch_registers");
669 register_valid
[GR1_REGNUM
] = 1;
671 #if defined(GR64_REGNUM) /* Read gr64-127 */
673 /* Global Registers gr64-gr95 */
675 From
.Space
= UDI29KGlobalRegs
;
677 To
= (UDIUInt32
*)®isters
[4 * GR64_REGNUM
];
679 if (err
= UDIRead(From
, To
, Count
, Size
, &CountDone
, HostEndian
))
680 error("UDIRead() failed in udi_fetch_registers");
682 for (i
= GR64_REGNUM
; i
< GR64_REGNUM
+ 32; i
++)
683 register_valid
[i
] = 1;
685 #endif /* GR64_REGNUM */
687 /* Global Registers gr96-gr127 */
689 From
.Space
= UDI29KGlobalRegs
;
691 To
= (UDIUInt32
*)®isters
[4 * GR96_REGNUM
];
693 if (err
= UDIRead(From
, To
, Count
, Size
, &CountDone
, HostEndian
))
694 error("UDIRead() failed in udi_fetch_registers");
696 for (i
= GR96_REGNUM
; i
< GR96_REGNUM
+ 32; i
++)
697 register_valid
[i
] = 1;
699 /* Local Registers */
701 From
.Space
= UDI29KLocalRegs
;
703 To
= (UDIUInt32
*)®isters
[4 * LR0_REGNUM
];
705 if (err
= UDIRead(From
, To
, Count
, Size
, &CountDone
, HostEndian
))
706 error("UDIRead() failed in udi_fetch_registers");
708 for (i
= LR0_REGNUM
; i
< LR0_REGNUM
+ 128; i
++)
709 register_valid
[i
] = 1;
711 /* Protected Special Registers */
713 From
.Space
= UDI29KSpecialRegs
;
715 To
= (UDIUInt32
*)®isters
[4 * SR_REGNUM(0)];
717 if (err
= UDIRead(From
, To
, Count
, Size
, &CountDone
, HostEndian
))
718 error("UDIRead() failed in udi_fetch_registers");
720 for (i
= SR_REGNUM(0); i
< SR_REGNUM(0) + 15; i
++)
721 register_valid
[i
] = 1;
723 if (USE_SHADOW_PC
) { /* Let regno_to_srnum() handle the register number */
724 fetch_register(NPC_REGNUM
);
725 fetch_register(PC_REGNUM
);
726 fetch_register(PC2_REGNUM
);
728 /* Unprotected Special Registers sr128-sr135 */
730 From
.Space
= UDI29KSpecialRegs
;
732 To
= (UDIUInt32
*)®isters
[4 * SR_REGNUM(128)];
734 if (err
= UDIRead(From
, To
, Count
, Size
, &CountDone
, HostEndian
))
735 error("UDIRead() failed in udi_fetch_registers");
737 for (i
= SR_REGNUM(128); i
< SR_REGNUM(128) + 135-128+1; i
++)
738 register_valid
[i
] = 1;
743 printf_unfiltered("Fetching all registers\n");
744 printf_unfiltered("Fetching PC0 = 0x%x, PC1 = 0x%x, PC2 = 0x%x\n",
745 read_register(NPC_REGNUM
), read_register(PC_REGNUM
),
746 read_register(PC2_REGNUM
));
749 /* There doesn't seem to be any way to get these. */
752 supply_register (FPE_REGNUM
, (char *) &val
);
753 supply_register (INTE_REGNUM
, (char *) &val
);
754 supply_register (FPS_REGNUM
, (char *) &val
);
755 supply_register (EXO_REGNUM
, (char *) &val
);
760 /********************************************************* UDI_STORE_REGISTERS
761 ** Store register regno into the target.
762 * If regno==-1 then store all the registers.
766 udi_store_registers (regno
)
774 UDIBool HostEndian
= 0;
778 store_register(regno
);
784 printf_unfiltered("Storing all registers\n");
785 printf_unfiltered("PC0 = 0x%x, PC1 = 0x%x, PC2 = 0x%x\n", read_register(NPC_REGNUM
),
786 read_register(PC_REGNUM
), read_register(PC2_REGNUM
));
791 From
= (UDIUInt32
*)®isters
[4 * GR1_REGNUM
];
792 To
.Space
= UDI29KGlobalRegs
;
795 if(UDIWrite(From
, To
, Count
, Size
, &CountDone
, HostEndian
))
796 error("UDIWrite() failed in udi_store_regisetrs");
798 #if defined(GR64_REGNUM)
800 /* Global registers gr64-gr95 */
802 From
= (UDIUInt32
*)®isters
[4 * GR64_REGNUM
];
803 To
.Space
= UDI29KGlobalRegs
;
806 if(UDIWrite(From
, To
, Count
, Size
, &CountDone
, HostEndian
))
807 error("UDIWrite() failed in udi_store_regisetrs");
809 #endif /* GR64_REGNUM */
811 /* Global registers gr96-gr127 */
813 From
= (UDIUInt32
*)®isters
[4 * GR96_REGNUM
];
814 To
.Space
= UDI29KGlobalRegs
;
817 if(UDIWrite(From
, To
, Count
, Size
, &CountDone
, HostEndian
))
818 error("UDIWrite() failed in udi_store_regisetrs");
820 /* Local Registers */
822 From
= (UDIUInt32
*)®isters
[4 * LR0_REGNUM
];
823 To
.Space
= UDI29KLocalRegs
;
826 if(UDIWrite(From
, To
, Count
, Size
, &CountDone
, HostEndian
))
827 error("UDIWrite() failed in udi_store_regisetrs");
830 /* Protected Special Registers */ /* VAB through TMR */
832 From
= (UDIUInt32
*)®isters
[4 * SR_REGNUM(0)];
833 To
.Space
= UDI29KSpecialRegs
;
836 if(UDIWrite(From
, To
, Count
, Size
, &CountDone
, HostEndian
))
837 error("UDIWrite() failed in udi_store_regisetrs");
839 /* PC0, PC1, PC2 possibly as shadow registers */
841 From
= (UDIUInt32
*)®isters
[4 * SR_REGNUM(10)];
842 To
.Space
= UDI29KSpecialRegs
;
845 To
.Offset
= 20; /* SPC0 */
847 To
.Offset
= 10; /* PC0 */
848 if(UDIWrite(From
, To
, Count
, Size
, &CountDone
, HostEndian
))
849 error("UDIWrite() failed in udi_store_regisetrs");
851 /* PC1 via UDI29KPC */
853 From
= (UDIUInt32
*)®isters
[4 * PC_REGNUM
];
855 To
.Offset
= 0; /* PC1 */
857 if (UDIWrite (From
, To
, Count
, Size
, &CountDone
, HostEndian
))
858 error ("UDIWrite() failed in udi_store_regisetrs");
862 From
= (UDIUInt32
*)®isters
[4 * SR_REGNUM(13)];
863 To
.Space
= UDI29KSpecialRegs
;
866 if(UDIWrite(From
, To
, Count
, Size
, &CountDone
, HostEndian
))
867 error("UDIWrite() failed in udi_store_regisetrs");
869 /* Unprotected Special Registers */
871 From
= (UDIUInt32
*)®isters
[4 * SR_REGNUM(128)];
872 To
.Space
= UDI29KSpecialRegs
;
875 if(UDIWrite(From
, To
, Count
, Size
, &CountDone
, HostEndian
))
876 error("UDIWrite() failed in udi_store_regisetrs");
878 registers_changed ();
881 /****************************************************** UDI_PREPARE_TO_STORE */
882 /* Get ready to modify the registers array. On machines which store
883 individual registers, this doesn't need to do anything. On machines
884 which store all the registers in one fell swoop, this makes sure
885 that registers contains all the registers from the program being
889 udi_prepare_to_store ()
891 /* Do nothing, since we can store individual regs */
894 /********************************************************** TRANSLATE_ADDR */
899 #if defined(ULTRA3) && defined(KERNEL_DEBUGGING)
900 /* Check for a virtual address in the kernel */
901 /* Assume physical address of ublock is in paddr_u register */
902 /* FIXME: doesn't work for user virtual addresses */
903 if (addr
>= UVADDR
) {
904 /* PADDR_U register holds the physical address of the ublock */
905 CORE_ADDR i
= (CORE_ADDR
)read_register(PADDR_U_REGNUM
);
906 return(i
+ addr
- (CORE_ADDR
)UVADDR
);
914 /************************************************* UDI_XFER_INFERIOR_MEMORY */
915 /* FIXME! Merge these two. */
917 udi_xfer_inferior_memory (memaddr
, myaddr
, len
, write
)
924 memaddr
= translate_addr(memaddr
);
927 return udi_write_inferior_memory (memaddr
, myaddr
, len
);
929 return udi_read_inferior_memory (memaddr
, myaddr
, len
);
932 /********************************************************** UDI_FILES_INFO */
936 printf_unfiltered ("\tAttached to UDI socket to %s and running program %s.\n",
937 udi_config_id
, prog_name
);
940 /**************************************************** UDI_INSERT_BREAKPOINT */
942 udi_insert_breakpoint (addr
, contents_cache
)
944 char *contents_cache
;
949 for (cnt
= 0; cnt
< BKPT_TABLE_SIZE
; cnt
++)
950 if (bkpt_table
[cnt
].Type
== 0) /* Find first free slot */
953 if(cnt
>= BKPT_TABLE_SIZE
)
954 error("Too many breakpoints set");
956 bkpt_table
[cnt
].Addr
.Offset
= addr
;
957 bkpt_table
[cnt
].Addr
.Space
= UDI29KIRAMSpace
;
958 bkpt_table
[cnt
].PassCount
= 1;
959 bkpt_table
[cnt
].Type
= UDIBreakFlagExecute
;
961 err
= UDISetBreakpoint(bkpt_table
[cnt
].Addr
,
962 bkpt_table
[cnt
].PassCount
,
963 bkpt_table
[cnt
].Type
,
964 &bkpt_table
[cnt
].BreakId
);
966 if (err
== 0) return 0; /* Success */
968 bkpt_table
[cnt
].Type
= 0;
969 error("UDISetBreakpoint returned error code %d\n", err
);
972 /**************************************************** UDI_REMOVE_BREAKPOINT */
974 udi_remove_breakpoint (addr
, contents_cache
)
976 char *contents_cache
;
981 for (cnt
= 0; cnt
< BKPT_TABLE_SIZE
; cnt
++)
982 if (bkpt_table
[cnt
].Addr
.Offset
== addr
) /* Find matching breakpoint */
985 if(cnt
>= BKPT_TABLE_SIZE
)
986 error("Can't find breakpoint in table");
988 bkpt_table
[cnt
].Type
= 0;
990 err
= UDIClearBreakpoint(bkpt_table
[cnt
].BreakId
);
991 if (err
== 0) return 0; /* Success */
993 error("UDIClearBreakpoint returned error code %d\n", err
);
997 udi_kill(arg
,from_tty
)
1004 UDIStop does not really work as advertised. It causes the TIP to close it's
1005 connection, which usually results in GDB dying with a SIGPIPE. For now, we
1006 just invoke udi_close, which seems to get things right.
1010 udi_session_id
= -1;
1014 printf_unfiltered("Target has been stopped.");
1021 /* Keep the target around, e.g. so "run" can do the right thing when
1022 we are already debugging something. FIXME-maybe: should we kill the
1023 TIP with UDIDisconnect using UDITerminateSession, and then restart
1024 it on the next "run"? */
1030 Load a program into the target. Args are: `program {options}'. The options
1031 are used to control loading of the program, and are NOT passed onto the
1032 loaded code as arguments. (You need to use the `run' command to do that.)
1035 -ms %d Set mem stack size to %d
1036 -rs %d Set regular stack size to %d
1037 -i send init info (default)
1038 -noi don't send init info
1039 -[tT] Load Text section
1040 -[dD] Load Data section
1041 -[bB] Load BSS section
1042 -[lL] Load Lit section
1046 download(load_arg_string
, from_tty
)
1047 char *load_arg_string
;
1050 #define DEFAULT_MEM_STACK_SIZE 0x6000
1051 #define DEFAULT_REG_STACK_SIZE 0x2000
1058 int load_text
= 1, load_data
= 1, load_bss
= 1, load_lit
= 1;
1060 address_ranges
[0].Space
= UDI29KIRAMSpace
;
1061 address_ranges
[0].Offset
= 0xffffffff;
1062 address_ranges
[0].Size
= 0;
1064 address_ranges
[1].Space
= UDI29KDRAMSpace
;
1065 address_ranges
[1].Offset
= 0xffffffff;
1066 address_ranges
[1].Size
= 0;
1068 stack_sizes
[0] = DEFAULT_REG_STACK_SIZE
;
1069 stack_sizes
[1] = DEFAULT_MEM_STACK_SIZE
;
1073 filename
= strtok(load_arg_string
, " \t");
1075 error ("Must specify at least a file name with the load command");
1077 filename
= tilde_expand (filename
);
1078 make_cleanup (free
, filename
);
1080 while (token
= strtok (NULL
, " \t"))
1082 if (token
[0] == '-')
1086 if (STREQ (token
, "ms"))
1087 stack_sizes
[1] = atol (strtok (NULL
, " \t"));
1088 else if (STREQ (token
, "rs"))
1089 stack_sizes
[0] = atol (strtok (NULL
, " \t"));
1092 load_text
= load_data
= load_bss
= load_lit
= 0;
1115 error ("Unknown UDI load option -%s", token
-1);
1122 pbfd
= bfd_openr (filename
, gnutarget
);
1125 perror_with_name (filename
);
1127 make_cleanup (bfd_close
, pbfd
);
1132 if (!bfd_check_format (pbfd
, bfd_object
))
1133 error ("It doesn't seem to be an object file");
1135 for (section
= pbfd
->sections
; section
; section
= section
->next
)
1137 if (bfd_get_section_flags (pbfd
, section
) & SEC_ALLOC
)
1141 unsigned long section_size
, section_end
;
1142 const char *section_name
;
1144 section_name
= bfd_get_section_name (pbfd
, section
);
1145 if (STREQ (section_name
, ".text") && !load_text
)
1147 else if (STREQ (section_name
, ".data") && !load_data
)
1149 else if (STREQ (section_name
, ".bss") && !load_bss
)
1151 else if (STREQ (section_name
, ".lit") && !load_lit
)
1154 To
.Offset
= bfd_get_section_vma (pbfd
, section
);
1155 section_size
= bfd_section_size (pbfd
, section
);
1156 section_end
= To
.Offset
+ section_size
;
1158 if (section_size
== 0)
1159 /* This is needed at least in the BSS case, where the code
1160 below starts writing before it even checks the size. */
1163 printf_unfiltered("[Loading section %s at %x (%d bytes)]\n",
1168 if (bfd_get_section_flags (pbfd
, section
) & SEC_CODE
)
1170 To
.Space
= UDI29KIRAMSpace
;
1172 address_ranges
[0].Offset
= min (address_ranges
[0].Offset
,
1174 address_ranges
[0].Size
= max (address_ranges
[0].Size
,
1176 - address_ranges
[0].Offset
);
1180 To
.Space
= UDI29KDRAMSpace
;
1182 address_ranges
[1].Offset
= min (address_ranges
[1].Offset
,
1184 address_ranges
[1].Size
= max (address_ranges
[1].Size
,
1186 - address_ranges
[1].Offset
);
1189 if (bfd_get_section_flags (pbfd
, section
) & SEC_LOAD
) /* Text, data or lit */
1195 while (section_size
> 0)
1199 Count
= min (section_size
, 1024);
1201 bfd_get_section_contents (pbfd
, section
, buffer
, fptr
,
1204 err
= UDIWrite ((UDIHostMemPtr
)buffer
, /* From */
1207 (UDISizeT
)1, /* Size */
1208 &Count
, /* CountDone */
1209 (UDIBool
)0); /* HostEndian */
1211 error ("UDIWrite failed, error = %d", err
);
1215 section_size
-= Count
;
1221 unsigned long zero
= 0;
1223 /* Write a zero byte at the vma */
1224 /* FIXME: Broken for sections of 1-3 bytes (we test for
1226 err
= UDIWrite ((UDIHostMemPtr
)&zero
, /* From */
1228 (UDICount
)1, /* Count */
1229 (UDISizeT
)4, /* Size */
1230 &Count
, /* CountDone */
1231 (UDIBool
)0); /* HostEndian */
1233 error ("UDIWrite failed, error = %d", err
);
1238 /* Now, duplicate it for the length of the BSS */
1239 err
= UDICopy (From
, /* From */
1241 (UDICount
)(section_size
/4 - 1), /* Count */
1242 (UDISizeT
)4, /* Size */
1243 &Count
, /* CountDone */
1244 (UDIBool
)1); /* Direction */
1250 xerr
= UDIGetErrorMsg(err
, 100, message
, &Count
);
1252 fprintf_unfiltered (gdb_stderr
, "Error is %s\n", message
);
1254 fprintf_unfiltered (gdb_stderr
, "xerr is %d\n", xerr
);
1255 error ("UDICopy failed, error = %d", err
);
1262 entry
.Space
= UDI29KIRAMSpace
;
1263 entry
.Offset
= bfd_get_start_address (pbfd
);
1268 /* User interface to download an image into the remote target. See download()
1269 * for details on args.
1273 udi_load(args
, from_tty
)
1277 download (args
, from_tty
);
1279 symbol_file_add (strtok (args
, " \t"), from_tty
, 0, 0, 0, 0);
1282 /*************************************************** UDI_WRITE_INFERIOR_MEMORY
1283 ** Copy LEN bytes of data from debugger memory at MYADDR
1284 to inferior's memory at MEMADDR. Returns number of bytes written. */
1286 udi_write_inferior_memory (memaddr
, myaddr
, len
)
1296 UDICount CountDone
= 0;
1297 UDIBool HostEndian
= 0;
1299 To
.Space
= udi_memory_space(memaddr
);
1300 From
= (UDIUInt32
*)myaddr
;
1302 while (nwritten
< len
)
1303 { Count
= len
- nwritten
;
1304 if (Count
> MAXDATA
) Count
= MAXDATA
;
1305 To
.Offset
= memaddr
+ nwritten
;
1306 if(UDIWrite(From
, To
, Count
, Size
, &CountDone
, HostEndian
))
1307 { error("UDIWrite() failed in udi_write_inferrior_memory");
1311 { nwritten
+= CountDone
;
1318 /**************************************************** UDI_READ_INFERIOR_MEMORY
1319 ** Read LEN bytes from inferior memory at MEMADDR. Put the result
1320 at debugger address MYADDR. Returns number of bytes read. */
1322 udi_read_inferior_memory(memaddr
, myaddr
, len
)
1332 UDICount CountDone
= 0;
1333 UDIBool HostEndian
= 0;
1336 From
.Space
= udi_memory_space(memaddr
);
1337 To
= (UDIUInt32
*)myaddr
;
1340 { Count
= len
- nread
;
1341 if (Count
> MAXDATA
) Count
= MAXDATA
;
1342 From
.Offset
= memaddr
+ nread
;
1343 if(err
= UDIRead(From
, To
, Count
, Size
, &CountDone
, HostEndian
))
1344 { error("UDIRead() failed in udi_read_inferrior_memory");
1348 { nread
+= CountDone
;
1355 /********************************************************************* WARNING
1360 error ("ERROR while loading program into remote TIP: $d\n", num
);
1364 /*****************************************************************************/
1365 /* Fetch a single register indicatated by 'regno'.
1366 * Returns 0/-1 on success/failure.
1369 fetch_register (regno
)
1377 UDIBool HostEndian
= 0;
1381 if (regno
== GR1_REGNUM
)
1383 From
.Space
= UDI29KGlobalRegs
;
1386 else if (regno
>= GR96_REGNUM
&& regno
< GR96_REGNUM
+ 32)
1388 From
.Space
= UDI29KGlobalRegs
;
1389 From
.Offset
= (regno
- GR96_REGNUM
) + 96;;
1392 #if defined(GR64_REGNUM)
1394 else if (regno
>= GR64_REGNUM
&& regno
< GR64_REGNUM
+ 32 )
1396 From
.Space
= UDI29KGlobalRegs
;
1397 From
.Offset
= (regno
- GR64_REGNUM
) + 64;
1400 #endif /* GR64_REGNUM */
1402 else if (regno
>= LR0_REGNUM
&& regno
< LR0_REGNUM
+ 128)
1404 From
.Space
= UDI29KLocalRegs
;
1405 From
.Offset
= (regno
- LR0_REGNUM
);
1407 else if (regno
>=FPE_REGNUM
&& regno
<=EXO_REGNUM
)
1410 supply_register(160 + (regno
- FPE_REGNUM
),(char *) &val
);
1411 return; /* Pretend Success */
1415 From
.Space
= UDI29KSpecialRegs
;
1416 From
.Offset
= regnum_to_srnum(regno
);
1419 if (err
= UDIRead(From
, &To
, Count
, Size
, &CountDone
, HostEndian
))
1420 error("UDIRead() failed in udi_fetch_registers");
1422 supply_register(regno
, (char *) &To
);
1425 printf_unfiltered("Fetching register %s = 0x%x\n", reg_names
[regno
], To
);
1427 /*****************************************************************************/
1428 /* Store a single register indicated by 'regno'.
1429 * Returns 0/-1 on success/failure.
1432 store_register (regno
)
1441 UDIBool HostEndian
= 0;
1443 From
= read_register (regno
); /* get data value */
1446 printf_unfiltered("Storing register %s = 0x%x\n", reg_names
[regno
], From
);
1448 if (regno
== GR1_REGNUM
)
1450 To
.Space
= UDI29KGlobalRegs
;
1452 result
= UDIWrite(&From
, To
, Count
, Size
, &CountDone
, HostEndian
);
1453 /* Setting GR1 changes the numbers of all the locals, so invalidate the
1454 * register cache. Do this *after* calling read_register, because we want
1455 * read_register to return the value that write_register has just stuffed
1456 * into the registers array, not the value of the register fetched from
1459 registers_changed ();
1461 #if defined(GR64_REGNUM)
1462 else if (regno
>= GR64_REGNUM
&& regno
< GR64_REGNUM
+ 32 )
1464 To
.Space
= UDI29KGlobalRegs
;
1465 To
.Offset
= (regno
- GR64_REGNUM
) + 64;
1466 result
= UDIWrite(&From
, To
, Count
, Size
, &CountDone
, HostEndian
);
1468 #endif /* GR64_REGNUM */
1469 else if (regno
>= GR96_REGNUM
&& regno
< GR96_REGNUM
+ 32)
1471 To
.Space
= UDI29KGlobalRegs
;
1472 To
.Offset
= (regno
- GR96_REGNUM
) + 96;
1473 result
= UDIWrite(&From
, To
, Count
, Size
, &CountDone
, HostEndian
);
1475 else if (regno
>= LR0_REGNUM
&& regno
< LR0_REGNUM
+ 128)
1477 To
.Space
= UDI29KLocalRegs
;
1478 To
.Offset
= (regno
- LR0_REGNUM
);
1479 result
= UDIWrite(&From
, To
, Count
, Size
, &CountDone
, HostEndian
);
1481 else if (regno
>= FPE_REGNUM
&& regno
<= EXO_REGNUM
)
1482 return 0; /* Pretend Success */
1483 else if (regno
== PC_REGNUM
)
1485 /* PC1 via UDI29KPC */
1487 To
.Space
= UDI29KPC
;
1488 To
.Offset
= 0; /* PC1 */
1489 result
= UDIWrite (&From
, To
, Count
, Size
, &CountDone
, HostEndian
);
1491 /* Writing to this loc actually changes the values of pc0 & pc1 */
1493 register_valid
[PC_REGNUM
] = 0; /* pc1 */
1494 register_valid
[NPC_REGNUM
] = 0; /* pc0 */
1496 else /* An unprotected or protected special register */
1498 To
.Space
= UDI29KSpecialRegs
;
1499 To
.Offset
= regnum_to_srnum(regno
);
1500 result
= UDIWrite(&From
, To
, Count
, Size
, &CountDone
, HostEndian
);
1504 error("UDIWrite() failed in store_registers");
1508 /********************************************************** REGNUM_TO_SRNUM */
1510 * Convert a gdb special register number to a 29000 special register number.
1513 regnum_to_srnum(regno
)
1517 case VAB_REGNUM
: return(0);
1518 case OPS_REGNUM
: return(1);
1519 case CPS_REGNUM
: return(2);
1520 case CFG_REGNUM
: return(3);
1521 case CHA_REGNUM
: return(4);
1522 case CHD_REGNUM
: return(5);
1523 case CHC_REGNUM
: return(6);
1524 case RBP_REGNUM
: return(7);
1525 case TMC_REGNUM
: return(8);
1526 case TMR_REGNUM
: return(9);
1527 case NPC_REGNUM
: return(USE_SHADOW_PC
? (20) : (10));
1528 case PC_REGNUM
: return(USE_SHADOW_PC
? (21) : (11));
1529 case PC2_REGNUM
: return(USE_SHADOW_PC
? (22) : (12));
1530 case MMU_REGNUM
: return(13);
1531 case LRU_REGNUM
: return(14);
1532 case IPC_REGNUM
: return(128);
1533 case IPA_REGNUM
: return(129);
1534 case IPB_REGNUM
: return(130);
1535 case Q_REGNUM
: return(131);
1536 case ALU_REGNUM
: return(132);
1537 case BP_REGNUM
: return(133);
1538 case FC_REGNUM
: return(134);
1539 case CR_REGNUM
: return(135);
1540 case FPE_REGNUM
: return(160);
1541 case INTE_REGNUM
: return(161);
1542 case FPS_REGNUM
: return(162);
1543 case EXO_REGNUM
:return(164);
1545 return(255); /* Failure ? */
1548 /****************************************************************************/
1550 * Determine the Target memory space qualifier based on the addr.
1551 * FIXME: Can't distinguis I_ROM/D_ROM.
1552 * FIXME: Doesn't know anything about I_CACHE/D_CACHE.
1555 udi_memory_space(addr
)
1558 UDIUInt32 tstart
= IMemStart
;
1559 UDIUInt32 tend
= tstart
+ IMemSize
;
1560 UDIUInt32 dstart
= DMemStart
;
1561 UDIUInt32 dend
= tstart
+ DMemSize
;
1562 UDIUInt32 rstart
= RMemStart
;
1563 UDIUInt32 rend
= tstart
+ RMemSize
;
1565 if (((UDIUInt32
)addr
>= tstart
) && ((UDIUInt32
)addr
< tend
)) {
1566 return UDI29KIRAMSpace
;
1567 } else if (((UDIUInt32
)addr
>= dstart
) && ((UDIUInt32
)addr
< dend
)) {
1568 return UDI29KDRAMSpace
;
1569 } else if (((UDIUInt32
)addr
>= rstart
) && ((UDIUInt32
)addr
< rend
)) {
1570 /* FIXME: how do we determine between D_ROM and I_ROM */
1571 return UDI29KIROMSpace
;
1572 } else /* FIXME: what do me do now? */
1573 return UDI29KDRAMSpace
; /* Hmmm! */
1575 /*********************************************************************** STUBS
1578 void convert16() {;}
1579 void convert32() {;}
1580 GDB_FILE
* EchoFile
= 0; /* used for debugging */
1581 int QuietMode
= 0; /* used for debugging */
1583 #ifdef NO_HIF_SUPPORT
1587 return(0); /* Emulate a failure */
1591 /* Target_ops vector. Not static because there does not seem to be
1592 any portable way to do a forward declaration of a static variable.
1593 The RS/6000 doesn't like "extern" followed by "static"; SunOS
1594 /bin/cc doesn't like "static" twice. */
1596 struct target_ops udi_ops
= {
1598 "Remote UDI connected TIP",
1599 "Remote debug an AMD 29k using UDI socket connection to TIP process.\n\
1601 `configuration-id AF_INET hostname port-number'\n\
1602 To connect via the network, where hostname and port-number specify the\n\
1603 host and port where you can connect via UDI.\n\
1604 configuration-id is unused.\n\
1606 `configuration-id AF_UNIX socket-name tip-program'\n\
1607 To connect using a local connection to the \"tip.exe\" program which is\n\
1608 supplied by AMD. If socket-name specifies an AF_UNIX socket then the\n\
1609 tip program must already be started; connect to it using that socket.\n\
1610 If not, start up tip-program, which should be the name of the tip\n\
1611 program. If appropriate, the PATH environment variable is searched.\n\
1612 configuration-id is unused.\n\
1614 `configuration-id'\n\
1615 Look up the configuration in ./udi_soc or /etc/udi_soc, which\n\
1616 are files containing lines in the above formats. configuration-id is\n\
1617 used to pick which line of the file to use.",
1624 udi_fetch_registers
,
1625 udi_store_registers
,
1626 udi_prepare_to_store
,
1627 udi_xfer_inferior_memory
,
1629 udi_insert_breakpoint
,
1630 udi_remove_breakpoint
,
1631 0, /* termial_init */
1632 0, /* terminal_inferior */
1633 0, /* terminal_ours_for_output */
1634 0, /* terminal_ours */
1635 0, /* terminal_info */
1636 udi_kill
, /* FIXME, kill */
1638 0, /* lookup_symbol */
1639 udi_create_inferior
,
1640 udi_mourn
, /* mourn_inferior FIXME */
1642 0, /* notice_signals */
1645 1, /* has_all_memory */
1648 1, /* has_registers */
1649 1, /* has_execution */
1651 0, /* sections_end */
1652 OPS_MAGIC
, /* Always the last thing */
1656 _initialize_remote_udi ()
1658 add_target (&udi_ops
);