diff -Nru insight-5.3.92.orig/gdb/Makefile.in insight-5.3.92/gdb/Makefile.in --- insight-5.3.92.orig/gdb/Makefile.in 2003-08-18 20:10:52.000000000 +0200 +++ insight-5.3.92/gdb/Makefile.in 2003-09-21 09:42:16.000000000 +0200 @@ -2135,6 +2135,8 @@ $(remote_fileio_h) remote-hms.o: remote-hms.c $(defs_h) $(gdbcore_h) $(target_h) $(monitor_h) \ $(serial_h) $(regcache_h) +remote-m68k-bdm.o: remote-m68k-bdm.c $(bfd_h) $(wait_h) $(defs_h) $(inferior_h) \ + $(gdbcore_h) $(target_h) remote-mips.o: remote-mips.c $(defs_h) $(inferior_h) $(bfd_h) $(symfile_h) \ $(gdbcmd_h) $(gdbcore_h) $(serial_h) $(target_h) $(remote_utils_h) \ $(gdb_string_h) $(gdb_stat_h) $(regcache_h) diff -Nru insight-5.3.92.orig/gdb/config/m68k/bdm.mt insight-5.3.92/gdb/config/m68k/bdm.mt --- insight-5.3.92.orig/gdb/config/m68k/bdm.mt 1970-01-01 01:00:00.000000000 +0100 +++ insight-5.3.92/gdb/config/m68k/bdm.mt 2003-09-21 09:59:56.000000000 +0200 @@ -0,0 +1,5 @@ +# Target: m68k bdm interface for the CPU32 and Coldfire processors. +# +TM_CLIBS= -L$(prefix)/lib -lBDM +TDEPFILES= m68k-tdep.o remote-m68k-bdm.o +TM_FILE= tm-bdm.h diff -Nru insight-5.3.92.orig/gdb/config/m68k/tm-bdm.h insight-5.3.92/gdb/config/m68k/tm-bdm.h --- insight-5.3.92.orig/gdb/config/m68k/tm-bdm.h 1970-01-01 01:00:00.000000000 +0100 +++ insight-5.3.92/gdb/config/m68k/tm-bdm.h 2003-09-21 10:38:04.000000000 +0200 @@ -0,0 +1,134 @@ +/* + * Target machine description for Coldfire BDM (Moto 5200) + * Copyright (C) 1995 W. Eric Norum + * Copyright (C) 1998 Chris Johns (ccj@acm.org) + * + * Based on: + * 1. `A Background Debug Mode Driver Package for Motorola's + * 16- and 32-Bit Microcontrollers', Scott Howard, Motorola + * Canada, 1993. + * 2. `Linux device driver for public domain BDM Interface', + * M. Schraut, Technische Universitaet Muenchen, Lehrstuhl + * fuer Prozessrechner, 1995. + * 3. BDM support for gdb by W. Eric Norum + * Saskatchewan Accelerator Laboratory + * University of Saskatchewan + * 107 North Road + * Saskatoon, Saskatchewan, CANADA + * S7N 5C6 + * + * This file is part of GDB. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#include "breakpoint.h" + +/* + * Function prototypes + */ +extern unsigned char *m68k_bdm_breakpoint_from_pc (CORE_ADDR *pcptr, int *lenptr); +extern CORE_ADDR m68k_bdm_saved_pc_after_call (struct frame_info *); +extern const char *bdm_register_name (int i); +extern int cf_stopped_by_watchpoint (void); +extern int cf_can_use_watchpoint (enum target_hw_bp_type type, int cnt, int ot); +extern int cf_insert_watchpoint (CORE_ADDR addr, int len, enum target_hw_bp_type type); +extern int cf_remove_watchpoint (CORE_ADDR addr, int len, enum target_hw_bp_type type); +extern int cf_insert_hw_breakpoint (CORE_ADDR addr, char *shadow); +extern int cf_remove_hw_breakpoint (CORE_ADDR addr, char *shadow); +extern int cf_stopped_data_address (void); + + +/* + * Coldfire does it for us if we use PCC to get the PC + */ +#define DECR_PC_AFTER_BREAK 0 + +/* + * We have to control this directly as the CPU32 and Coldfire have different + * breakpoint opcodes. + */ +#define BREAKPOINT_FROM_PC m68k_bdm_breakpoint_from_pc + +/* + * Include the generic stuff + */ +#include "m68k/tm-m68k.h" + +/* + * Override some of the generic definitions + */ + +/* + * For uCLinux we need to detect we have a subroutine call + * which is really a trap #0. This should be caught by the + * the IN_SIGTRAMP handler defined above, but incase it is + * not we should try and catch it here. + */ + +#undef SAVED_PC_AFTER_CALL +#define SAVED_PC_AFTER_CALL(frame) \ + (m68k_bdm_saved_pc_after_call (frame)) + +/* + * we need 40 registers for the CPU32 and Coldfire: + * 8 data registers + * 8 address registers + * 2 other registers (PC, PS) + * 22 special registers (actual set depends on architecture) + * 0 floating point registers + */ +#undef NUM_REGS +#undef REGISTER_BYTES +#define NUM_REGS 40 +#define REGISTER_BYTES (16*4 + 2*4 + 22*4) + +#undef REGISTER_NAMES +#define REGISTER_NAME(i) bdm_register_name(i) + +#undef FP0_REGNUM +#undef FPC_REGNUM +#undef FPS_REGNUM +#undef FPI_REGNUM +#define FP0_REGNUM 40 /* Floating point register 0 */ +#define FPC_REGNUM FP0_REGNUM + 8 /* 68881 control register */ +#define FPS_REGNUM FPC_REGNUM + 1 /* 68881 status register */ +#define FPI_REGNUM FPS_REGNUM + 1 /* 68881 iaddr register */ + +/* + * The other definitions and macros don't need to be changed: + * a) The Coldfire has no floating point registers + * b) The REGISTER_BYTES_OK macro isn't used + */ + +#define TARGET_HAS_HARDWARE_WATCHPOINTS + +/* We need to remove watchpoints when stepping, else we hit them again! */ + +#define HAVE_NONSTEPPABLE_WATCHPOINT 1 + +#define STOPPED_BY_WATCHPOINT(w) (cf_stopped_by_watchpoint ()) + +/* Use these macros for watchpoint insertion/deletion. */ +/* type can be 0: write watch, 1: read watch, 2: access watch (read/write) */ + +#define TARGET_CAN_USE_HARDWARE_WATCHPOINT(type, cnt, ot) \ + (cf_can_use_watchpoint (type, cnt, ot)) + +#define target_insert_watchpoint(addr, len, type) (cf_insert_watchpoint (addr, len, type)) +#define target_remove_watchpoint(addr, len, type) (cf_remove_watchpoint (addr, len, type)) +#define target_insert_hw_breakpoint(addr, shadow) (cf_insert_hw_breakpoint (addr, shadow)) +#define target_remove_hw_breakpoint(addr, shadow) (cf_remove_hw_breakpoint (addr, shadow)) +#define target_stopped_data_address() (cf_stopped_data_address ()) diff -Nru insight-5.3.92.orig/gdb/configure.tgt insight-5.3.92/gdb/configure.tgt --- insight-5.3.92.orig/gdb/configure.tgt 2003-08-26 00:57:50.000000000 +0200 +++ insight-5.3.92/gdb/configure.tgt 2003-09-21 09:42:16.000000000 +0200 @@ -121,6 +121,8 @@ m68000-*-sunos3*) gdb_target=sun2os3 ;; m68000-*-sunos4*) gdb_target=sun2os4 ;; +m68*-bdm-*) gdb_target=bdm ;; + m68*-bull-sysv*) gdb_target=dpx2 ;; m68*-att-*) gdb_target=3b1 ;; m68*-cisco*-*) gdb_target=cisco ;; diff -Nru insight-5.3.92.orig/gdb/doc/gdb.texinfo insight-5.3.92/gdb/doc/gdb.texinfo --- insight-5.3.92.orig/gdb/doc/gdb.texinfo 2003-08-09 17:10:35.000000000 +0200 +++ insight-5.3.92/gdb/doc/gdb.texinfo 2003-09-21 09:42:16.000000000 +0200 @@ -11773,6 +11773,7 @@ * H8/500:: Hitachi H8/500 * M32R/D:: Mitsubishi M32R/D * M68K:: Motorola M68K +* Motorola BDM:: Motorola M68K/Coldfire Background Debug Mode * MIPS Embedded:: MIPS Embedded * OpenRISC 1000:: OpenRisc 1000 * PA:: HP PA Embedded @@ -12047,6 +12048,10 @@ @item target abug @var{dev} ABug ROM monitor for M68K. +@kindex target bdm +Background Debug Mode interface to Motorola 68k/Coldfire machine. +@xref{Motorola BDM, ,@value{GDBN} and Motorola 68k/Coldfire BDM}. + @kindex target cpu32bug @item target cpu32bug @var{dev} CPU32BUG monitor, running on a CPU32 (M68K) board. @@ -12073,6 +12078,101 @@ @end table + +@node Motorola BDM +@subsection @value{GDBN} and Motorola BDM + +@cindex BDM +@cindex CPU32 +@cindex Coldfire +Background Debug Mode (@dfn{BDM}) provides a full set of debug options +including the ability to: +@itemize @bullet +@item Insert breakpoints +@item Single-step +@item Display register contents +@item Display memory contents +@item Modify register contents +@item Modify memory contents +@end itemize + +A small interface circuit connects the BDM interface port on the +target machine to a parallel printer port on the debugging host. +A target system can be configured and a program downloaded and +executed with no bootstrap memory on the target machine and no other +connection between the debugging host and the target machine. + +The @code{target} command tells @value{GDBN} +to debug a program running on a target machine +@xref{Target Commands, ,Commands for managing targets}. +For example, the following command tells @value{GDBN} to use a BDM +interface connected to a ColdFire processor and the @code{LPT0} parallel port: +@example +target bdm /dev/bdmcf0 +@end example + +Do not attempt to use the parallel port for any other purpose while +@value{GDBN} is using it to control a BDM target. + +Once the BDM target has been selected a few other commands become +available: + +@table @code +@item bdm_reset +@kindex bdm_reset +Reset the target machine and enable BDM operation in the target. + +@item bdm_restart +@kindex bdm_restart +Reset the target machine and disable BDM operation in the target. +This command is useful only if the target machine has some kind of +bootstrap memory installed. + +@item bdm_status +@kindex bdm_status +Print the status of the target machine and the BDM interface. + +@item bdm_setdelay @var{N} +@kindex bdm_setdelay +Some BDM interface circuits can not handle high-speed data transfer. +This command lets you insert a delay between each BDM clock. +The larger the value of @var{N}, the longer the delay. +On most machines the default delay of @var{0} should work just fine. + +@item bdm_setdebug @var{N} +@kindex bdm_setdebug +Setting the level (@var{N}) to a non-zero value turns on +debugging messages in the BDM support library. + +@item bdm_setdriverdebug @var{N} +@kindex bdm_setdriverdebug +Setting the level (@var{N}) to a non-zero value turns on +debugging messages in the BDM device driver. + +@end table + +The registers which can be displayed and modified are: +@itemize @bullet +@item The data registers: @code{$d0}-@code{$d7} +@item The address registers: @code{$a0}-@code{$a5}, @code{$fp}, @code{$sp} +@item The program counter: @code{$pc} +@item The status register: @code{$ps} +@item The program counter at the beginning of the most recently executed +instruction: @code{$pcc} +@item The user stack pointer: @code{$usp} +@item The supervisor stack pointer: @code{$ssp} +@item The source function code register: @code{$sfc} +@item The destinaton function code register: @code{$dfc} +@item The vector base register: @code{$vbr} +@item The fault address register: @code{$far} +@item The BDM temporary register: @code{$atemp} +@item The module base address register: @code{$mbar} +@end itemize + +Target processor interrupts are disabled during single-step (step, next, +stepi, nexti) operations. + + @node MIPS Embedded @subsection MIPS Embedded diff -Nru insight-5.3.92.orig/gdb/remote-m68k-bdm.c insight-5.3.92/gdb/remote-m68k-bdm.c --- insight-5.3.92.orig/gdb/remote-m68k-bdm.c 1970-01-01 01:00:00.000000000 +0100 +++ insight-5.3.92/gdb/remote-m68k-bdm.c 2003-09-21 12:54:52.000000000 +0200 @@ -0,0 +1,1730 @@ +/* + * Motorola Background Debug Mode Target + * Copyright (C) 1995 W. Eric Norum + * Copyright (C) 1998 Chris Johns (ccj@acm.org) + * Copyright (C) 2000 Bryan Feir (bryan@sgl.crestech.ca) + * + * Based on: + * 1. `A Background Debug Mode Driver Package for Motorola's + * 16- and 32-Bit Microcontrollers', Scott Howard, Motorola + * Canada, 1993. + * 2. `Linux device driver for public domain BDM Interface', + * M. Schraut, Technische Universitaet Muenchen, Lehrstuhl + * fuer Prozessrechner, 1995. + * 3. BDM support for gdb by W. Eric Norum + * Saskatchewan Accelerator Laboratory + * University of Saskatchewan + * 107 North Road + * Saskatoon, Saskatchewan, CANADA + * S7N 5C6 + * 4. Coldfire support added by C Johns. + * 5. Hardware breakpoint support added by B Feir. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + * + * W. Eric Norum + * Saskatchewan Accelerator Laboratory + * University of Saskatchewan + * 107 North Road + * Saskatoon, Saskatchewan, CANADA + * S7N 5C6 + * + * eric@skatter.usask.ca + * + * Coldfire support by: + * Chris Johns + * Objective Design Systems + * 35 Cairo Street + * Cammeray, Sydney, 2062, Australia + * + * ccj@acm.org + * + * Coldfire hardware breakpoint support by: + * Bryan Feir + * CRESTech (Centre for Research in Earth and Space Technology) + * 4850 Keele Street, 1st floor + * Toronto, Ontario, CANADA M6E 3E5 + * + * bryan@sgl.crestech.ca + */ + +/* + * $Revision: 1.3 $ $Date: 2004/03/28 23:10:39 $ $Author: codewiz $ + */ + +#include "defs.h" +#include "gdbcore.h" +#include "target.h" +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "gdbcmd.h" +#include "command.h" +#include "inferior.h" +#include "value.h" +#include "breakpoint.h" +#include "regcache.h" +#include "BDMlib.h" + +extern struct target_ops bdm_ops; /* Forward declaration */ + +/* + * The name of the BDM driver special file + */ +static char *dev_name; +static int cpu_type; + +/* + * The different register names for the processors. + */ +static const char *cpu32plus_reg_names[NUM_REGS] = { + "d0", "d1", "d2", "d3", "d4", "d5", "d6", "d7", + "a0", "a1", "a2", "a3", "a4", "a5", "fp", "sp", + "ps", "pc", + "pcc", "usp", "ssp", "sfc", "dfc", "atemp", "far", + "vbr", + NULL, NULL, NULL, NULL, + "mbar", + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, +}; + +static const char *cpu32_reg_names[NUM_REGS] = { + "d0", "d1", "d2", "d3", "d4", "d5", "d6", "d7", + "a0", "a1", "a2", "a3", "a4", "a5", "fp", "sp", + "ps", "pc", + "pcc", "usp", "ssp", "sfc", "dfc", NULL, NULL, + "vbr", + NULL, NULL, NULL, NULL, + NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, +}; + +static const char *cf_reg_names[NUM_REGS] = { + "d0", "d1", "d2", "d3", "d4", "d5", "d6", "d7", + "a0", "a1", "a2", "a3", "a4", "a5", "fp", "sp", + "ps", "pc", + NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "vbr", + "cacr", "acr0", "acr1", "rambar", + "mbar", + "csr", "aatr", "tdr", "pbr", "pbmr", "abhr", "ablr", "dbr", "dbmr", +}; + +static const char **bdm_reg_names = cpu32plus_reg_names; + +const char *bdm_register_name(int i) +{ + if ((i < 0) || (i >= NUM_REGS)) + return NULL; + return bdm_reg_names[i]; +} + +static int reg_to_dev_num[] = { + BDM_REG_SR, + BDM_REG_RPC, + BDM_REG_PCC, + BDM_REG_USP, + BDM_REG_SSP, + BDM_REG_SFC, + BDM_REG_DFC, + BDM_REG_ATEMP, + BDM_REG_FAR, + BDM_REG_VBR, + BDM_REG_CACR, + BDM_REG_ACR0, + BDM_REG_ACR1, + BDM_REG_RAMBAR, + BDM_REG_MBAR, + BDM_REG_CSR, + BDM_REG_AATR, + BDM_REG_TDR, + BDM_REG_PBR, + BDM_REG_PBMR, + BDM_REG_ABHR, + BDM_REG_ABLR, + BDM_REG_DBR, + BDM_REG_DBMR + }; + +/* + * The name of the most recently loaded program + */ +static char *bdm_prog_loaded; + +/* + * Do not load the program when creating the target. + */ +static int bdm_no_load; + +/* + * default delay for interface + */ +#define BDM_DEFAULT_DELAY 0 +static int bdm_delay = -1; + +/* + * does gdb wait or not, only valid for a Coldfire processor + */ +static int bdm_gdb_no_wait = 0; + +/* + * Hold BDM ATEMP register (CPU32 only). + */ +static unsigned long atemp; +static int haveAtemp; + +static int hit_watchpoint; + +/* + * CF BDM Debug hardware version number. + */ + +static unsigned long cf_debug_ver; + +/* + * Not sure if this is defined somewhere. Cannot see anywhere. + */ +extern int (*ui_loop_hook) (int); + +/* + * Forward declarations + */ +static void bdm_load (char *, int); + +/* + * give target time to come up after reset + * time in usec + */ +#define TIME_TO_COME_UP 60000 + +/* + * Downloader routines + */ +static int downLoaderReturn; +static int downLoaderFirst; +static unsigned long downLoadBaseAddress, downLoadStartAddress; +static unsigned long downLoadDataCount=0; +static int bdmDebugLevel; +static const char *downloadErrorString; + +static void +downloadSection (bfd *abfd, sec_ptr sec, PTR ignore) +{ + unsigned long dfc; + unsigned long address; + unsigned long nleft, size; + int count; + file_ptr offset; + char cbuf[1024]; + + /* + * See if the section needs loading + */ + if (bdmDebugLevel) + printf_filtered ("Section flags:%#x\n", bfd_get_section_flags (abfd, sec)); + if ((downLoaderReturn < 0) || + ((bfd_get_section_flags (abfd, sec) & SEC_HAS_CONTENTS) == 0) || + ((bfd_get_section_flags (abfd, sec) & SEC_LOAD) == 0)) + return; + address = bfd_section_lma (abfd, sec); + if (bdmDebugLevel) + printf_filtered ("Section address:%#lx\n", address); + if (downLoaderFirst && (bfd_get_section_flags (abfd, sec) & SEC_CODE)) { + downLoadStartAddress = bfd_get_start_address (abfd); + downLoadBaseAddress = address; + downLoaderFirst = 0; + if (bdmDebugLevel) + printf_filtered ("Start address:%#lx Base address:%#lx\n", + downLoadStartAddress, downLoadBaseAddress); + } + + /* + * Set the appropriate destination address space + */ + if (bfd_get_section_flags (abfd, sec) & SEC_CODE) + dfc = 0x6; /* Supervisor program space */ + else + dfc = 0x5; /* Supervisor data space */ + if (bdmWriteSystemRegister (BDM_REG_DFC, dfc) < 0) { + downLoaderReturn = -1; + return; + } + + /* + * Load the section in `sizeof cbuf` chunks + */ + size = nleft = bfd_get_section_size_before_reloc (sec); + if (nleft == 0) + return; + + /* Is this really necessary? I guess it gives the user something + to look at during a long download. */ + ui_out_message (uiout, 0, "Loading section %s, size 0x%s lma 0x%s\n", + sec->name, paddr_nz (size), paddr_nz (address)); + + offset = 0; + while (nleft) { + if (nleft > sizeof cbuf) + count = sizeof cbuf; + else + count = nleft; + if (!bfd_get_section_contents (abfd, sec, cbuf, offset, count)) { + downloadErrorString = "Error reading section contents"; + downLoaderReturn = -1; + return; + } + if (bdmWriteMemory (address, cbuf, count) < 0) { + downLoaderReturn = -1; + return; + } + + address += count; + offset += count; + nleft -= count; + if (quit_flag + || (ui_load_progress_hook != NULL + && ui_load_progress_hook (sec->name, offset))) + error ("Canceled the download"); + + if (show_load_progress != NULL) + show_load_progress (sec->name, offset, size, size, size); + } + downLoadDataCount += size; +} + +/* + * Load an executable image into the target + */ +static int +loadExecutable (const char *name) +{ + bfd *abfd; + unsigned long dfc; + unsigned long l; + + /* + * Make sure target is there + */ + if (!bdmCheck ()) + return -1; + + /* + * Open and verify the file + */ + bfd_init (); + abfd = bfd_openr (name, "default"); + if (abfd == NULL) { + downloadErrorString = bfd_errmsg (bfd_get_error()); + return -1; + } + if (!bfd_check_format (abfd, bfd_object)) { + downloadErrorString = "Not an object file"; + return -1; + } + + /* + * Save the destination function code register + */ + if (bdmReadSystemRegister (BDM_REG_DFC, &dfc) < 0) + return -1; + + /* + * Load each section of the executable file + */ + downLoadDataCount = 0; + downLoaderFirst = 1; + downLoaderReturn = 0; + bfd_map_over_sections (abfd, downloadSection, NULL); + if (downLoaderReturn < 0) + return -1; + + ui_out_text (uiout, "Start address "); + ui_out_field_fmt (uiout, "address", "0x%s", paddr_nz (downLoadStartAddress)); + ui_out_text (uiout, ", load size "); + ui_out_field_fmt (uiout, "load-size", "%lu", downLoadDataCount); + ui_out_text (uiout, "\n"); + + /* + * Set program counter + */ + if ((bdmWriteSystemRegister (BDM_REG_RPC, downLoadStartAddress) < 0) + || (bdmWriteSystemRegister (BDM_REG_DFC, dfc) < 0)) + return -1; + return 0; + + inferior_ptid = pid_to_ptid (1); + +} + +/* + * The breakpoint codes for the different processors + */ +static char cpu32_breakpoint[] = {0x4a, 0xfa}; +static char cf_breakpoint[] = {0x4a, 0xc8}; +static char *breakpointCode; +static int breakpointSize; + +static int cf_init_watchpoints(); + +#ifdef SYSCALL_TRAP +/* Immediately after a function call, return the saved pc before the frame + is setup. For uCLinux which uses a TRAP #0 for a system call we need to + read the first long word of the stack to see if the stack frame format is + type 4 and the vector is 32 (0x4080), and the opcode at the PC is + "move.w #0x2700,sr". If it is then get the second long from the stack. */ + +CORE_ADDR +m68k_bdm_saved_pc_after_call (struct frame_info *frame) +{ + unsigned int op; + unsigned int eframe; + int sp; + + sp = read_register (SP_REGNUM); + eframe = read_memory_integer (sp, 2); + op = read_memory_integer (frame->pc, 4); + + /* + * This test could break if some changes the syste call. + */ + + if (eframe == 0x4080 && op == 0x46fc2700) + return read_memory_integer (sp + 4, 4); + else + return read_memory_integer (sp, 4); +} +#endif /* SYSCALL_TRAP */ + +unsigned char *m68k_bdm_breakpoint_from_pc (CORE_ADDR *pcptr, int *lenptr) +{ + *lenptr = breakpointSize; + return breakpointCode; +} + +/* + * Short pause + */ +static void +nap (int microseconds) +{ + struct timeval tv; + + tv.tv_sec = microseconds / 1000000; + tv.tv_usec = microseconds % 1000000; + select (0, NULL, NULL, NULL, &tv); +} + +/* + * Display error message and jump back to main input loop + */ +static void +bdm_report_error (void) +{ + error ("BDM error: %s", bdmErrorString ()); +} + +/* + * Initialize bdm interface port + */ +static void +bdm_init (int tty, char *arg) +{ +} + +/* + * Return interface status + */ +static int +bdm_get_status (void) +{ + int status; + + if ((status = bdmStatus ()) < 0) + bdm_report_error (); + return status; +} + +static void +bdm_get_status_interactive (int pid, char *arg) +{ + printf ("BDM status: 0x%x\n", bdm_get_status ()); +} + +/* + * release chip: reset and disable bdm mode + */ +static void +bdm_release_chip (void) +{ + haveAtemp = 0; + registers_changed (); + if (bdmRelease () < 0) + bdm_report_error (); +} + +/* + * stop chip + */ +static void +bdm_stop_chip (void) +{ + if (bdmStop () < 0) + bdm_report_error (); +} + +/* + * Allow chip to resume execution + */ +static void +bdm_go (void) +{ + haveAtemp = 0; + if (bdmGo () < 0) + bdm_report_error (); +} + +/* + * Reset chip, enter BDM mode + */ +static void +bdm_reset (void) +{ + registers_changed (); + if (bdmReset () < 0) + bdm_report_error (); + nap (TIME_TO_COME_UP); +} + +/* + * step cpu32 chip: execute a single instruction + * This is complicated by the presence of interrupts. + * Consider the following sequence of events: + * - User attempts to `continue' from a breakpoint. + * - Gdb calls bdm_step_chip to single-step the instruction that + * had been replaced by the BGND instruction. + * - The target processor executes the instruction and stops. + * - GDB replaces the instruction with a BGND instruction to + * force a breakpoint the next time the instruction is hit. + * - GDB calls bdm_go and the target resumes execution. + * This all seems fine, but now consider what happens when a interrupt + * is pending: + * - User attempts to `continue' from a breakpoint. + * - Gdb calls bdm_step_chip to single-step the instruction that + * had been replaced by the BGND instruction. + * - The target processor does not execute the replaced instruction, + * but rather executes the first instruction of the interrupt + * service routine, then stops. + * - GDB replaces the instruction with a BGND instruction to + * force a breakpoint the next time the instruction is hit. + * - GDB calls bdm_go and the target resumes execution. + * - The target finishes off the interrupt, and upon returing from + * the interrupt generates another breakpoint! + * The solution is simple -- disable interrupts when single stepping. + * The problem then becomes the handling of instructions which involve + * the program status word! + */ +static void +bdm_step_cpu32_chip (void) +{ + unsigned long pc; + unsigned short instruction; + unsigned short immediate; + unsigned long d7; + unsigned long sr; + unsigned long nsr; + enum { + op_other, + op_ANDIsr, + op_EORIsr, + op_ORIsr, + op_TOsr, + op_FROMsr, + op_FROMsrTOd7 + } op; + + /* + * Get the existing status register + */ + if (bdmReadSystemRegister (BDM_REG_SR, &sr) < 0) + bdm_report_error (); + + /* + * Read the instuction about to be executed + */ + if ((bdmReadSystemRegister (BDM_REG_RPC, &pc) < 0) + || (bdmReadWord (pc, &instruction) < 0)) + bdm_report_error (); + + /* + * See what operation is to be performed + */ + if (instruction == 0x027C) + op = op_ANDIsr; + else if (instruction == 0x0A7C) + op = op_EORIsr; + else if (instruction == 0x007C) + op = op_ORIsr; + else if (instruction == 0x40C7) + op = op_FROMsrTOd7; + else if ((instruction & 0xFFC0) == 0x40C0) + op = op_FROMsr; + else if ((instruction & 0xFFC0) == 0x46C0) + op = op_TOsr; + else + op = op_other; + + /* + * Set things up for the single-step operation + */ + switch (op) { + case op_FROMsr: + /* + * It's storing the SR somewhere. + * Store the SR in D7 and change the instruction + * to save D7. This fails if the addressing mode + * is one of the esoteric modes that uses D7 as + * and index register, but we'll just have to hope + * that doesn't happen too often. + */ + if ((bdmReadRegister (7, &d7) < 0) + || (bdmWriteRegister (7, sr) < 0) + || (bdmWriteWord (pc, 0x3007 | + ((instruction & 0x38) << 3) | + ((instruction & 0x07) << 9)) < 0)) + bdm_report_error (); + break; + + case op_ANDIsr: + case op_EORIsr: + case op_ORIsr: + /* + * It's an immediate operation to the SR -- pick up the value + */ + if (bdmReadWord (pc+2, &immediate) < 0) + bdm_report_error (); + break; + + case op_TOsr: + case op_other: + break; + } + + /* + * Ensure the step is done with interrupts disabled + */ + if (bdmWriteSystemRegister (BDM_REG_SR, sr | 0x0700) < 0) + bdm_report_error (); + + /* + * Do the single-step + */ + if (bdmStep () < 0) + bdm_report_error (); + + /* + * Get the ATEMP register since the following operations may + * modify it. + */ + if (bdmReadSystemRegister (BDM_REG_ATEMP, &atemp) < 0) + bdm_report_error (); + haveAtemp = 1; + + /* + * Clean things up + */ + switch (op) { + case op_FROMsr: + if ((bdmWriteRegister (7, d7) < 0) + || (bdmWriteWord (pc, instruction) < 0) + || (bdmWriteSystemRegister (BDM_REG_SR, sr) < 0)) + bdm_report_error (); + break; + + case op_FROMsrTOd7: + if ((bdmReadRegister (7, &d7) < 0) + || (bdmWriteRegister (7, (d7 & ~0xFFFF) | (sr & 0xFFFF)) < 0) + || (bdmWriteSystemRegister (BDM_REG_SR, sr) < 0)) + bdm_report_error (); + break; + + case op_ANDIsr: + if (bdmWriteSystemRegister (BDM_REG_SR, sr & immediate) < 0) + bdm_report_error (); + break; + + case op_EORIsr: + if (bdmWriteSystemRegister (BDM_REG_SR, sr ^ immediate) < 0) + bdm_report_error (); + break; + + case op_ORIsr: + if (bdmWriteSystemRegister (BDM_REG_SR, sr | immediate) < 0) + bdm_report_error (); + break; + + case op_TOsr: + break; + + case op_other: + if ((bdmReadSystemRegister (BDM_REG_SR, &nsr) < 0) + || (bdmWriteSystemRegister (BDM_REG_SR, (nsr & ~0x0700) | (sr & 0x0700)) < 0)) + bdm_report_error (); + break; + } +} + +static void +bdm_step_chip (void) +{ + /* + * The cpu32 is harder to step than the Coldfire. + */ + if (cpu_type == BDM_CPU32) { + bdm_step_cpu32_chip(); + return; + } + + /* + * Do the single-step + */ + if (bdmStep () < 0) + bdm_report_error (); +} + +/* + * true if runnable + */ +static int +bdm_can_run (void) +{ + return 1; +} + +static void +bdm_setdelay(int delay) +{ + if (bdmSetDelay (delay) < 0) + bdm_report_error (); +} + +static void +bdm_setdelay_interactive (char *arg, int from_tty) +{ + char *dummy; + + if (!arg) { + if (bdm_delay >= 0) + printf_filtered("bdm_delay is %d", bdm_delay); + else + printf_filtered("using default delay %d", BDM_DEFAULT_DELAY); + } + else { + bdm_delay = strtoul(arg, &dummy, 0); + bdm_setdelay (bdm_delay); + } +} + +static void +bdm_setdebug_interactive (char *arg, int from_tty) +{ + char *dummy; + + if (arg) { + bdmDebugLevel = strtoul(arg, &dummy, 0); + bdmSetDebugFlag (bdmDebugLevel); + } + else + error ("Argument missing"); +} + +static void +bdm_setdriverdebug_interactive (char *arg, int from_tty) +{ + char *dummy; + + if (arg) + bdmSetDriverDebugFlag (strtoul(arg, &dummy, 0)); + else + error ("Argument missing"); +} + +static void +bdm_set_no_wait (char *arg, int from_tty) +{ + bdm_gdb_no_wait = 1; +} + +static void +bdm_set_wait (char *arg, int from_tty) +{ + if (cpu_type == BDM_CPU32) { + error ("No wait mode is not supported on a CPU32"); + return; + } + if (bdm_get_status ()) + bdm_gdb_no_wait = 0; + else + error ("The target is running, please stop first"); +} + +static void +bdm_issue_stop (char *arg, int from_tty) +{ + bdm_stop_chip (); +} + +/* + * Open a connection the target via bdm + * name is the devicename of bdm and the filename to be used + * used for communication. + */ +static void +bdm_open (char *name, int from_tty) +{ + char *p; + int version; + unsigned long csr; + + if (bdmIsOpen ()) + error ("Bdm is already open, must close it first"); + if (name == NULL) + error ("Use `target bdm ' to use the bdm target"); + + /* + * Find the first whitespace character after device and chop it off + */ + for (p = name; (*p != '\0') && (!isspace (*p)); p++) ; + if ((*p == '\0') && (p == name)) + error ("Please include the name the bdm port device."); + dev_name = savestring (name, p - name); + + target_preopen (from_tty); + unpush_target (&bdm_ops); + + if (bdmOpen (dev_name) < 0) + bdm_report_error (); + if (bdmStatus () & (BDM_TARGETPOWER | BDM_TARGETNC)) { + bdmClose (); + error ("Target or cable problem"); + } + + /* + * Ask the driver for it's version. + * We are only interested in the major number when checking the + * driver version number. + */ + if (bdmGetDrvVersion (&version) < 0) + bdm_report_error (); + if ((version & 0xff00) != (BDM_DRV_VERSION & 0xff00)) { + printf_filtered ("Incorrect driver version, looking for %i.%i"\ + " and found %i.%i\n", + BDM_DRV_VERSION >> 8, BDM_DRV_VERSION & 0xff, + version >> 8, version & 0xff); + bdmClose (); + error ("Can't run with wrong BDM driver"); + } + + /* + * Get the processor type. + */ + if (bdmGetProcessor (&cpu_type) < 0) + bdm_report_error (); + switch (cpu_type) { + case BDM_CPU32: + bdm_reg_names = cpu32_reg_names; + breakpointCode = cpu32_breakpoint; + breakpointSize = sizeof cpu32_breakpoint; + break; + + case BDM_COLDFIRE: + bdm_reg_names = cf_reg_names; + breakpointCode = cf_breakpoint; + breakpointSize = sizeof cf_breakpoint; + cf_init_watchpoints(); + + /* + * Read the CSR register to determine the debug module + * version. + */ + if (bdmReadSystemRegister (BDM_REG_CSR, &csr) < 0) + bdm_report_error (); + cf_debug_ver = (csr >> 20) & 0x0f; + break; + + default: + bdmClose (); + error ("Unknown processor type returned from the driver."); + } + + push_target (&bdm_ops); + + if (bdm_delay >= 0) + bdm_setdelay (bdm_delay); + else + bdm_setdelay (BDM_DEFAULT_DELAY); + if (from_tty) + printf_filtered ("Remote %s connected to %s\n", + target_shortname, dev_name); + if (cpu_type == BDM_COLDFIRE) + printf_filtered (" Coldfire debug module version is %ld (%s)\n", + cf_debug_ver, + cf_debug_ver == 0 ? "5206(e)" : "5307/5407(e)"); +} + +/* + * Terminate current application and return to system prompt. + * On a target, just let the program keep on running + */ +static void +bdm_kill (void) +{ +#ifdef BDM_GDB_RELEASE_CPU_ON_EXIT + if (bdm_get_status () & BDM_TARGETSTOPPED) + bdm_go (); +#else + bdm_stop_chip (); + bdm_reset (); +#endif + bdm_prog_loaded = 0; +} + +static void +bdm_close (quitting) +int quitting; +{ + if (quitting) + bdm_kill (); + bdmClose (); +} + +/* + * _detach -- Terminate the open connection to the remote debugger. + * takes a program previously attached to and detaches it. + * We better not have left any breakpoints + * in the program or it'll die when it hits one. + * Close the open connection to the remote debugger. + * Use this when you want to detach and do something else + * with your gdb. + */ +static void +bdm_detach (char *args, int from_tty) +{ + pop_target (); /* calls bdm_close to do the real work */ +} + +/* + * _resume -- Tell the remote machine to resume. + */ +static void +bdm_resume (ptid_t pid, int step, enum target_signal sig) +{ + if (step) + bdm_step_chip (); + else + bdm_go (); +} + +/* + * We have fallen into an exception supported by the runtime system. + * by executing a `breakpoint' instruction. + */ +static void +analyze_exception (struct target_waitstatus *status) +{ + unsigned long pc, sp; + unsigned short vec; + char opcode[20]; /* `big enough' */ + + if (cpu_type == BDM_CPU32) { + if (bdmReadSystemRegister (BDM_REG_PCC, &pc) < 0) + bdm_report_error (); + } + else { + if (bdmReadSystemRegister (BDM_REG_RPC, &pc) < 0) + bdm_report_error (); + if (pc) + pc -= 2; + } + status->kind = TARGET_WAITKIND_STOPPED; + + /* + * See if it was a `breakpoint' instruction + */ + if (bdmReadMemory (pc, opcode, breakpointSize) < 0) + bdm_report_error (); + if (memcmp (breakpointCode, opcode, breakpointSize) == 0) { + if (bdmWriteSystemRegister (BDM_REG_RPC, pc) < 0) + bdm_report_error (); + status->value.sig = TARGET_SIGNAL_TRAP; + return; + } + /* + * FIXME: Why an illegal instruction signal ? + */ + status->value.sig = TARGET_SIGNAL_ILL; +} + +static int sigintFlag; +static void +bdm_signal_handler (int s) +{ + sigintFlag++; +} + +/* + * Wait until the remote machine stops, then return, + * storing status in status just as `wait' would. + */ +static ptid_t +bdm_wait (ptid_t pid, struct target_waitstatus *status) +{ + unsigned long csr; + int bdm_stat; + int detach = 0; + int ui_count = 0; + void (*ofunc) (); + + hit_watchpoint = 0; + if (bdm_gdb_no_wait) { + status->kind = TARGET_WAITKIND_STOPPED; + status->value.sig = TARGET_SIGNAL_GRANT; + return null_ptid; + } + + status->kind = TARGET_WAITKIND_EXITED; + status->value.integer = 0; + + /* + * Catch SIGINT signals + */ + sigintFlag = 0; + ofunc = signal (SIGINT, bdm_signal_handler); + + /* + * A work around a problem with the 5206e processor. Not sure + * what the issue is. It could be the processor. + */ + if (cpu_type == BDM_COLDFIRE && cf_debug_ver == 0) + nap (10000); + + /* + * Wait here till the target requires service + */ + while ((bdm_stat = bdm_get_status ()) == 0) { + ui_count = 0; + while (ui_count++ < 6) { + nap (50000); + + /* N.B. The UI may destroy our world (for instance by calling + remote_stop,) in which case we want to get out of here as + quickly as possible. It is not safe to touch scb, since + someone else might have freed it. The ui_loop_hook signals that + we should exit by returning 1. */ + + if (ui_loop_hook) + detach = ui_loop_hook (0); + + if (detach || sigintFlag) + bdm_stop_chip (); + } + } + + signal (SIGINT, ofunc); + + /* + * Determine why the target stopped + */ + switch (bdm_stat) { + case BDM_TARGETNC: + status->kind = TARGET_WAITKIND_EXITED; + status->value.integer = 9999; + break; + case BDM_TARGETPOWER: + status->kind = TARGET_WAITKIND_STOPPED; + status->value.sig = TARGET_SIGNAL_PWR; + break; + case BDM_TARGETRESET: + status->kind = TARGET_WAITKIND_STOPPED; + status->value.sig = TARGET_SIGNAL_ABRT; + break; + case BDM_TARGETSTOPPED: + case BDM_TARGETHALT: + case BDM_TARGETSTOPPED | BDM_TARGETHALT: + if (sigintFlag) { + status->kind = TARGET_WAITKIND_STOPPED; + status->value.sig = TARGET_SIGNAL_TSTP; + } + else { + if (cpu_type == BDM_CPU32) { + if (!haveAtemp + && (bdmReadSystemRegister (BDM_REG_ATEMP, &atemp) < 0)) + bdm_report_error (); + switch (atemp & 0xffff) { + case 0xffff: /* double bus fault */ + status->kind = TARGET_WAITKIND_STOPPED; + status->value.sig = TARGET_SIGNAL_BUS; + break; + case 0x0: /* HW bkpt */ + status->kind = TARGET_WAITKIND_STOPPED; + status->value.sig = TARGET_SIGNAL_TRAP; + break; + case 0x1: /* background mode */ + analyze_exception (status); + break; + default: + printf_filtered ("bdm_wait: Unknown atemp:%#lx\n", atemp); + status->kind = TARGET_WAITKIND_STOPPED; + status->value.sig = TARGET_SIGNAL_GRANT; + } + } + else { + if (bdmReadSystemRegister (BDM_REG_CSR, &csr) < 0) + bdm_report_error (); + if (csr & 0x08000000) { /* double bus fault */ + status->kind = TARGET_WAITKIND_STOPPED; + status->value.sig = TARGET_SIGNAL_BUS; + } + else { + if (csr & 0x04000000) { /* hardware trigger */ + hit_watchpoint = 1; + status->kind = TARGET_WAITKIND_STOPPED; + status->value.sig = TARGET_SIGNAL_TRAP; + } + else { + if (csr & 0x01000000) { /* -BKPT signal */ + status->kind = TARGET_WAITKIND_STOPPED; + status->value.sig = TARGET_SIGNAL_TRAP; + } + else { + if (csr & 0x02000000) { /* HALT/software bkpt */ + analyze_exception (status); + } + else { + printf_filtered ("bdm_wait: Unknown csr:%#lx", + csr); + status->kind = TARGET_WAITKIND_STOPPED; + status->value.sig = TARGET_SIGNAL_GRANT; + } + } + } + } + } + } + break; + default: + printf_filtered ("bdm_wait: Unknown BDM status: %#x", bdm_stat); + break; + } + haveAtemp = 0; + return null_ptid; +} + +/* + * The following routines handle the Coldfire hardware breakpoints. Only one + * breakpoint supported so far, and it can be either a PC breakpoint or an + * address watchpoint. Unfortunately, the TARGET_CAN_USE_HARDWARE_WATCHPOINT + * macro only allows for bounds checking within one of the two types and not + * limits that cover the sum of both, so extra work is needed. + * + * (Actually, very few processors seem to have much support for that routine + * at all.) + * + * As a result, the way this is handled is that the can_use routine will allow + * the first breakpoint of either type to be added. Any further checking so + * that only one of the two can be used is done later when GDB actually tries + * to create the breakpoints, usually when the processor is restarted. + * + * We keep a local copy of the breakpoints list becasue the chain that GDB + * keeps isn't exported globally. + * + * While things could be simplified with only one breakpoint present, setting + * up more general routines allows for later expansion if newer versions of + * the ColdFire chip support more breakpoints at once. + * + * Also, the ColdFire supports things like multi-level triggers and triggers + * based on the data bus instead of just the address bus. The GDB commands + * don't allow for access to this, but much of it isn't necessary anyway, + * as GDB has its own method of handling 'breakpoint conditions' that is + * sufficient for most tasks. + */ + +#define TDR_TRC_DDATA 0x00000000 +#define TDR_TRC_HALT 0x40000000 +#define TDR_TRC_DINT 0x80000000 +#define TDR_L2_EBL 0x20000000 +#define TDR_L2_ALL 0x1FFF0000 +#define TDR_L2_EDLW 0x10000000 +#define TDR_L2_EDWL 0x08000000 +#define TDR_L2_EDWU 0x04000000 +#define TDR_L2_EDLL 0x02000000 +#define TDR_L2_EDLM 0x01000000 +#define TDR_L2_EDUM 0x00800000 +#define TDR_L2_EDUU 0x00400000 +#define TDR_L2_DI 0x00200000 +#define TDR_L2_EAI 0x00100000 +#define TDR_L2_EAR 0x00080000 +#define TDR_L2_EAL 0x00040000 +#define TDR_L2_EPC 0x00020000 +#define TDR_L2_PCI 0x00010000 +#define TDR_L1_EBL 0x00002000 +#define TDR_L1_ALL 0x00001FFF +#define TDR_L1_EDLW 0x00001000 +#define TDR_L1_EDWL 0x00000800 +#define TDR_L1_EDWU 0x00000400 +#define TDR_L1_EDLL 0x00000200 +#define TDR_L1_EDLM 0x00000100 +#define TDR_L1_EDUM 0x00000080 +#define TDR_L1_EDUU 0x00000040 +#define TDR_L1_DI 0x00000020 +#define TDR_L1_EAI 0x00000010 +#define TDR_L1_EAR 0x00000008 +#define TDR_L1_EAL 0x00000004 +#define TDR_L1_EPC 0x00000002 +#define TDR_L1_PCI 0x00000001 + +struct cf_break { + enum target_hw_bp_type type; + CORE_ADDR addr; + int len; +}; + +#define CF_BREAKPOINT_MAX 1 + +static struct cf_break cf_breakpoints[CF_BREAKPOINT_MAX]; +static int cf_breakpoint_count; + +static int +cf_init_watchpoints(void) +{ + if (cpu_type != BDM_COLDFIRE) { + return(-1); + } + cf_breakpoint_count = 0; + if (bdmWriteSystemRegister (BDM_REG_TDR, TDR_TRC_HALT) < 0) + bdm_report_error (); + return(0); +} + +int +cf_stopped_by_watchpoint(void) +{ + return hit_watchpoint; +} + +int +cf_can_use_watchpoint(enum target_hw_bp_type type, int cnt, int ot) +{ + unsigned long tdr; + + if (cpu_type != BDM_COLDFIRE) { + return(0); + } + + if (type == bp_hardware_breakpoint || type == bp_read_watchpoint || + type == bp_hardware_watchpoint || type == bp_access_watchpoint) { + if (cnt <= 1) { + return(1); + } + } + + return(-1); +} + +int +cf_insert_hw_breakpoint(CORE_ADDR addr, char *shadow) +{ + unsigned long tdr; + + if (cpu_type != BDM_COLDFIRE) { + return(-1); + } + + if (cf_breakpoint_count < CF_BREAKPOINT_MAX) { + cf_breakpoints[cf_breakpoint_count].type = hw_execute; + cf_breakpoints[cf_breakpoint_count].addr = addr; + cf_breakpoints[cf_breakpoint_count++].len = 2; + + if (bdmReadSystemRegister (BDM_REG_TDR, &tdr) < 0) + bdm_report_error (); + tdr = ((tdr & ~TDR_L1_ALL) | (TDR_L1_EBL|TDR_L1_EPC)); + if (bdmWriteSystemRegister (BDM_REG_PBR, addr) < 0) + bdm_report_error (); + if (bdmWriteSystemRegister (BDM_REG_PBMR, 0) < 0) + bdm_report_error (); + if (bdmWriteSystemRegister (BDM_REG_TDR, tdr) < 0) + bdm_report_error (); + if (bdmDebugLevel) + printf_filtered ("Insert PC Breakpoint @0x%08lx\n", addr); + } + else { + return(-1); + } + return(0); +} + +static int +cf_check_breakpoint(type, addr, len) + enum target_hw_bp_type type; + CORE_ADDR addr; + int len; +{ + int i; + + for (i = 0; i < cf_breakpoint_count; i++) { + if (cf_breakpoints[i].type == type && + cf_breakpoints[i].addr == addr && + cf_breakpoints[i].len == len) { + for (; i < CF_BREAKPOINT_MAX-1; i++) { + cf_breakpoints[i] = cf_breakpoints[i+1]; + } + cf_breakpoint_count--; + return(1); + } + } + return(0); +} + +int +cf_remove_hw_breakpoint(CORE_ADDR addr, char *shadow) +{ + unsigned long tdr; + unsigned long csr; + + if (cpu_type != BDM_COLDFIRE) { + return(-1); + } + + if (cf_check_breakpoint(hw_execute, addr, 2)) { + if (bdmReadSystemRegister (BDM_REG_TDR, &tdr) < 0) + bdm_report_error (); + tdr &= ~TDR_L1_EPC; + if ((tdr & TDR_L1_ALL) == 0) { + tdr &= ~TDR_L1_EBL; + } + if (bdmWriteSystemRegister (BDM_REG_TDR, tdr) < 0) + bdm_report_error (); + if (bdmDebugLevel) + printf_filtered ("Remove PC Breakpoint @0x%08lx\n", addr); + } + else { + return(-1); + } + return(0); +} + +#define AATR_READONLY 0x7F85 +#define AATR_WRITEONLY 0x7F05 +#define AATR_READWRITE 0xFF05 + +int +cf_insert_watchpoint(CORE_ADDR addr, int len, enum target_hw_bp_type type) +{ + unsigned long tdr; + + if (cpu_type != BDM_COLDFIRE) { + return(-1); + } + + if (cf_breakpoint_count < CF_BREAKPOINT_MAX) { + cf_breakpoints[cf_breakpoint_count].type = type; + cf_breakpoints[cf_breakpoint_count].addr = addr; + cf_breakpoints[cf_breakpoint_count++].len = len; + + if (bdmReadSystemRegister (BDM_REG_TDR, &tdr) < 0) + bdm_report_error (); + tdr = ((tdr & ~TDR_L1_ALL) | (TDR_L1_EBL|TDR_L1_EAR)); + if (bdmWriteSystemRegister (BDM_REG_ABLR, addr) < 0) + bdm_report_error (); + if (bdmWriteSystemRegister (BDM_REG_ABHR, addr+len-1) < 0) + bdm_report_error (); + if (type == hw_read) { + if (bdmWriteSystemRegister (BDM_REG_AATR, AATR_READONLY) < 0) + bdm_report_error (); + if (bdmDebugLevel) + printf_filtered ("Insert read Watchpoint @0x%08lx-0x%08lx\n", + addr, addr+len-1); + } + else if (type == hw_write) { + if (bdmWriteSystemRegister (BDM_REG_AATR, AATR_WRITEONLY) < 0) + bdm_report_error (); + if (bdmDebugLevel) + printf_filtered ("Insert write Watchpoint @0x%08lx-0x%08lx\n", + (long unsigned int)addr, addr+len-1); + } + else { + if (bdmWriteSystemRegister (BDM_REG_AATR, AATR_READWRITE) < 0) + bdm_report_error (); + if (bdmDebugLevel) + printf_filtered ("Insert access Watchpoint @0x%08lx-0x%08lx\n", + addr, addr+len-1); + } + if (bdmWriteSystemRegister (BDM_REG_TDR, tdr) < 0) + bdm_report_error (); + } + else { + return(-1); + } + return(0); +} + +int +cf_remove_watchpoint(CORE_ADDR addr, int len, enum target_hw_bp_type type) +{ + unsigned long tdr; + unsigned long csr; + + if (cpu_type != BDM_COLDFIRE) { + return(-1); + } + + if (cf_check_breakpoint(type, addr, len)) { + if (bdmReadSystemRegister (BDM_REG_TDR, &tdr) < 0) + bdm_report_error (); + tdr &= ~TDR_L1_EAR; + if ((tdr & TDR_L1_ALL) == 0) { + tdr &= ~TDR_L1_EBL; + } + if (bdmWriteSystemRegister (BDM_REG_TDR, tdr) < 0) + bdm_report_error (); + if (bdmDebugLevel) + printf_filtered ("Remove %s Watchpoint @0x%08lx-0x%08lx\n", + (type == hw_read) ? "read" : + ((type == hw_write) ? "write" : "access"), + addr, addr+len-1); + } + else { + return(-1); + } + return(0); +} + +int +cf_stopped_data_address(void) +{ + unsigned long tdr; + unsigned long ablr; + + if (cpu_type != BDM_COLDFIRE) { + return(-1); + } + + if (bdmReadSystemRegister (BDM_REG_TDR, &tdr) < 0) + bdm_report_error (); + if (bdmReadSystemRegister (BDM_REG_ABLR, &ablr) < 0) + bdm_report_error (); + + if (tdr & TDR_L1_EAR) { + return(ablr); + } + return(0); +} + +/* This is called not only when we first attach, but also when the + user types "run" after having attached. */ +void +bdm_create_inferior (char *execfile, char *args, char **env) +{ + char *prg_file = NULL; + unsigned long entry_pt; + + clear_proceed_status (); + init_wait_for_inferior (); + if (*args) { + prg_file = args; + } + else { + prg_file = execfile; + } + if (!(prg_file) && !(bdm_prog_loaded)) + error ("No program specified to run\n"); + else + { + if (!bdm_no_load) { + if (bdm_prog_loaded) + printf_filtered ("Note: `%s' has already been loaded.\n", + bdm_prog_loaded); + if (query ("Do you want to download `%s'?", prg_file)) + bdm_load (prg_file, 0); + if (bdmReadSystemRegister (BDM_REG_RPC, &entry_pt) < 0) + bdm_report_error (); + } + proceed (entry_pt, TARGET_SIGNAL_DEFAULT, 0); + } + inferior_ptid = pid_to_ptid (1); +} + +/* + * Fetch register REGNO, or all user registers if REGNO is -1. + */ +static void +bdm_fetch_register (int regno) +{ + unsigned long l; + char cbuf[4]; + int ret; + + if (regno < 0) { + for (regno = 0 ; regno < NUM_REGS ; regno++) + bdm_fetch_register (regno); + } + else { + /* + * When the target is running the + * cpu registers can not be accessed. + */ + if (bdm_gdb_no_wait && (bdm_get_status () == 0)) { + l = 0; + ret = 0; + } + else { + if (regno < 16) { + ret = bdmReadRegister (regno, &l); + } + else { + if ((regno - 16) < (sizeof (reg_to_dev_num) / sizeof (int))) { + ret = bdmReadSystemRegister (reg_to_dev_num[regno - 16], &l); + } + else { + error ("Bad register number (%d)", regno); + return; + } + } + } + if (ret < 0) + bdm_report_error (); + cbuf[0] = l >> 24; + cbuf[1] = l >> 16; + cbuf[2] = l >> 8; + cbuf[3] = l; + supply_register (regno, cbuf); + } +} + +void +bdm_prepare_to_store (void) +{ + /* Do nothing, since we can store individual regs */ +} + +/* + * Store register REGNO, or all user registers if REGNO == -1. + */ +void +bdm_store_register (int regno) +{ + unsigned long l; + int ret; + + if (bdm_gdb_no_wait && (bdm_get_status () == 0)) + return; + + if (regno == -1) { + for (regno = 0 ; regno < NUM_REGS ; regno++) + bdm_store_register (regno); + } + else { + l = read_register (regno); + if (regno < 16) { + ret = bdmWriteRegister (regno, l); + } + else { + if ((regno - 16) < (sizeof (reg_to_dev_num) / sizeof (int))) { + ret = bdmWriteSystemRegister (reg_to_dev_num[regno - 16], l); + } + else { + error ("Bad register number (%d)", regno); + return; + } + } + if (ret < 0) + bdm_report_error (); + } +} + +/* + * Transfer memory contents between target and host + */ +static int +bdm_xfer_inferior_memory (CORE_ADDR memaddr, char *myaddr, + int len, int write, + struct mem_attrib *attrib, + struct target_ops *t) +{ + int ret; + + if (write) + ret = bdmWriteMemory (memaddr, myaddr, len); + else + ret = bdmReadMemory (memaddr, myaddr, len); + if (ret < 0) + bdm_report_error (); + return len; +} + +static void +bdm_files_info (struct target_ops *t) +{ + printf_filtered ("target %s is attached to %s\n", t->to_shortname, dev_name); + if (bdm_prog_loaded) { + printf_filtered ("and running program %s\n", bdm_prog_loaded); + } + else { + printf_filtered ("no program loaded\n"); + } +} + +/* + * Load a file. + */ +static void +bdm_load (char *args, int from_tty) +{ + char *p; + + if (bdm_prog_loaded) { + free (bdm_prog_loaded); + bdm_prog_loaded = NULL; + } + if (!args) { + error ( + "The bdmload command must include the filename to load.\n" + "You may want to use 'run', which uses the file given\n" + "on the command line when gdb was invoked."); + } + if ((bdm_get_status () & BDM_TARGETSTOPPED) == 0) + bdm_stop_chip (); + + /* strip off additional (unwanted) arguments after file name */ + for (p = args; (*p != '\0') && (!isspace (*p)); p++) ; + *p = '\0'; + + if (loadExecutable (args) < 0) + error ("%s", downloadErrorString); + bdm_prog_loaded = savestring (args, strlen (args)); +} + +/* + * Toggle the no load variable. + */ +static void +bdm_toggle_no_load (char *args, int from_tty) +{ + if (bdm_no_load) { + bdm_no_load = 0; + printf_filtered ("Image not loaded on run\n"); + } + else { + bdm_no_load = 1; + printf_filtered ("Image loaded on run\n"); + } +} + +/* + * Select a CPU32 processor register set. + */ +static void +bdm_select_cpu32 (char *args, int from_tty) +{ + bdm_reg_names = cpu32_reg_names; +} + +struct target_ops bdm_ops; + +static void +init_bdm_ops(void) +{ + bdm_ops.to_shortname = "bdm"; + bdm_ops.to_longname = "CPU32 and Coldfire Background Debug Mode Interface for downloading and remote debugging"; + bdm_ops.to_doc = "Uses the Public Domain Background Debug Mode Interface connected to the\n" +"BDM-port of the CPU32 or Coldfire based microcontroller and to a parallel port\n" +"of the PC.\n" +"Usage: target bdm \n" +"where is the BDM character special file (e.g. /dev/bdm0)."; + bdm_ops.to_open = bdm_open; + bdm_ops.to_close = bdm_close; + bdm_ops.to_detach = bdm_detach; + bdm_ops.to_resume = bdm_resume; + bdm_ops.to_wait = bdm_wait; + bdm_ops.to_fetch_registers = bdm_fetch_register; + bdm_ops.to_store_registers = bdm_store_register; + bdm_ops.to_prepare_to_store = bdm_prepare_to_store; + bdm_ops.to_xfer_memory = bdm_xfer_inferior_memory; + bdm_ops.to_files_info = bdm_files_info; + bdm_ops.to_insert_breakpoint = memory_insert_breakpoint; + bdm_ops.to_remove_breakpoint = memory_remove_breakpoint; + bdm_ops.to_kill = bdm_kill; + bdm_ops.to_load = bdm_load; + bdm_ops.to_stop = bdm_stop_chip; + bdm_ops.to_create_inferior = bdm_create_inferior; + bdm_ops.to_mourn_inferior = generic_mourn_inferior; + bdm_ops.to_can_run = bdm_can_run; + bdm_ops.to_stratum = process_stratum; + bdm_ops.to_has_all_memory = 1; + bdm_ops.to_has_memory = 1; + bdm_ops.to_has_stack = 1; + bdm_ops.to_has_registers = 1; + bdm_ops.to_has_execution = 1; + bdm_ops.to_magic = OPS_MAGIC; +}; + +void +_initialize_remote_bdmcf (void) +{ + init_bdm_ops (); + add_com ("bdm_reset", class_obscure, + (void (*)(char *, int))bdm_reset, + "Reset target and enter BDM mode."); + add_com ("bdm_release", class_obscure, + (void (*)(char *, int))bdm_release_chip, + "Reset target without BDM-mode."); + add_com ("bdm_status", class_obscure, + (void (*)(char *, int))bdm_get_status_interactive, + "Show status of bdm interface\n"); + add_com ("bdm_setdelay", class_obscure, + bdm_setdelay_interactive, + "set delay for download"); + add_com ("bdm_setdebug", class_obscure, + bdm_setdebug_interactive, + "enable/disable BDM diagnostic messages"); + add_com ("bdm_setdriverdebug", class_obscure, + bdm_setdriverdebug_interactive, + "enable/disable BDM driver diagnostic messages"); + add_com ("bdm_no_wait", class_obscure, + bdm_set_no_wait, + "Cause GDB to not wait for the target to stop when running."); + add_com ("bdm_wait", class_obscure, + bdm_set_wait, + "Cause GDB to wait for the target to stop when running."); + add_com ("bdm_stop", class_obscure, + bdm_issue_stop, + "Stop the target if running."); + add_com ("bdm-select-cpu32", class_obscure, + bdm_select_cpu32, + "Selects the CPU32 register set rather than the default CPU32+."); + add_com ("bdm-no-load", class_obscure, + bdm_toggle_no_load, + "Toggle the loading of the program to memory when asked to run."); + + add_target (&bdm_ops); +} diff -Nru insight-5.3.92.orig/gdb/infcmd.c insight-5.3.92/gdb/infcmd.c --- insight-5.3.92.orig/gdb/infcmd.c 2003-11-18 23:46:48.000000000 +0100 +++ insight-5.3.92/gdb/infcmd.c 2003-11-19 10:19:02.000000000 +0100 @@ -1271,8 +1271,10 @@ "finish_command: function has no target type"); /* FIXME: Shouldn't we do the cleanups before returning? */ - if (TYPE_CODE (value_type) == TYPE_CODE_VOID) + if (TYPE_CODE (value_type) == TYPE_CODE_VOID) { + do_cleanups (old_chain); return; + } funcaddr = BLOCK_START (SYMBOL_BLOCK_VALUE (function));