diff -u -r --new-file gdb-6.0.orig/gdb/arch-utils.c gdb-6.0/gdb/arch-utils.c --- gdb-6.0.orig/gdb/arch-utils.c 2003-06-19 11:04:55.000000000 -0400 +++ gdb-6.0/gdb/arch-utils.c 2005-01-25 22:27:18.000000000 -0500 @@ -339,7 +339,10 @@ int generic_register_size (int regnum) { - gdb_assert (regnum >= 0 && regnum < NUM_REGS + NUM_PSEUDO_REGS); + + // fprintf(stderr, "generic_register_size(%d)\n", regnum); + // causes problems on 68HC12 in banked mode + // gdb_assert (regnum >= 0 && regnum < NUM_REGS + NUM_PSEUDO_REGS); if (gdbarch_register_type_p (current_gdbarch)) return TYPE_LENGTH (gdbarch_register_type (current_gdbarch, regnum)); else Binary files gdb-6.0.orig/gdb/arch-utils.o and gdb-6.0/gdb/arch-utils.o differ Binary files gdb-6.0.orig/gdb/gdb and gdb-6.0/gdb/gdb differ Binary files gdb-6.0.orig/gdb/libgdb.a and gdb-6.0/gdb/libgdb.a differ diff -u -r --new-file gdb-6.0.orig/gdb/m68hc11-rom.c gdb-6.0/gdb/m68hc11-rom.c --- gdb-6.0.orig/gdb/m68hc11-rom.c 2004-08-26 23:59:40.000000000 -0400 +++ gdb-6.0/gdb/m68hc11-rom.c 2005-06-15 22:28:20.000000000 -0400 @@ -18,6 +18,8 @@ along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ +// Modifications to support D-Bug12 based BDM pods on HCS12 cpus with +// ppage register (such as MC9S12DP256) added by Mark Whitis #include "defs.h" #include "gdbcore.h" @@ -29,12 +31,32 @@ #include "event-top.h" #include "target.h" #include "inferior.h" +#include +#include "regcache.h" #include +#include "gdbarch.h" +#include "m68hc11-tdep.h" +#include "command.h" #ifndef __MINGW32__ #include #endif -/* Register numbers of various important registers. */ + +#define ASYNC + // If async is not defined, there will be some problems: + // - program location can be displayed incorrectly after + // a continue, step, next, etc. + // - commands will not wait until execution has finished + // - next or step commands may not stop where they are supposed to, + // probably because gdb uses the wrong value of the + // program counter and thus sets the breakpoint at the + // wrong location + // - ddd will not show the proper location + // If async is defined, there will be the following problem: + // - Program will begin execution as soon as the debugger + // loads. Use "pod reset" to stop. + +/* Register numpbers of various important registers. */ #define HARD_X_REGNUM 0 #define HARD_D_REGNUM 1 #define HARD_Y_REGNUM 2 @@ -44,9 +66,14 @@ #define HARD_A_REGNUM 5 #define HARD_B_REGNUM 6 #define HARD_CCR_REGNUM 7 +#define HARD_PP_REGNUM 8 + #define M68HC11_LAST_HARD_REG (HARD_CCR_REGNUM) #define M68HC11_NUM_REGS (8) - +#define M68HC12_LAST_HARD_REG (HARD_PP_REGNUM) +#define M68HC12_NUM_REGS (9) +#define M68HC12_HARD_PC_REGNUM 46 +#define M68HC12_NUM_PSEUDO_REGS (32 + 5 + 1) /* Switch gdb to use the given architecture. The architecture is controlled by the monitor we are connected to, not by our program. Each time we connect to the monitor, update the gdb-arch to @@ -493,8 +520,15 @@ "X", "D", "Y", "SP", "PC", "A", "B", "CCR" }; +static char *dbugS12_regnames[M68HC12_NUM_REGS] = +{ + "X", "D", "Y", "SP", "PC", "A", "B", "CCR", "PP" +}; + static struct target_ops dbug_ops; +static struct target_ops dbugS12_ops; static struct monitor_ops dbug_cmds; +static struct monitor_ops dbugS12_cmds; /* Initialization strings to wakeup the monitor. Send both \r and \030 (^X) to abort a possible current command. */ @@ -587,6 +621,98 @@ return 0; } + +static int +dbugS12_dumpregs (void) +{ + char buf[512]; + int resp_len; + char *p; + int i; + static int reg_list[] = { + HARD_PP_REGNUM, + HARD_PC_REGNUM, + HARD_SP_REGNUM, + HARD_X_REGNUM, + HARD_Y_REGNUM, + HARD_D_REGNUM, + -1 + }; + + // FIXME: this code is prone to buffer overlows if it does not + // get its expected response. + + /* Send the dump register command to the monitor and + get the reply. */ + monitor_printf ("rd\r"); + monitor_printf_noecho ("\r"); + resp_len = monitor_expect_prompt (buf, sizeof (buf)); + + p = buf; + while (p && strncmp (p, "CCR = SXHI NZVC", 15) != 0) { + p++; + if(p >= (buf + sizeof(buf) - 18)) return(1); + } + if (p == 0) + { + return -1; + } + + /* Skip the CCR marker. */ + while (p && p[0] != '\r' && p[0] != '\n') + p++; + + /* Skip end of line markers. */ + while (p && (p[0] == '\r' || p[0] == '\n')) + p++; + + for (i = 0; p && reg_list[i] >= 0; i++) + { + char *q; + + q = strchr (p, ' '); + if (q == 0) + q = strchr (p, '\t'); + + if (q) + *q++ = 0; + + /* Value for register D is split with ':' ex: 45:23. */ + if (p[2] == ':') + { + p[2] = p[1]; + p[1] = p[0]; + p++; + } + monitor_supply_register (reg_list[i], p); + p = q; + while (p && p[0] == ' ') + p++; + } + + /* Last value is the CCR expressed in bits. */ + if (p) + { + int bit, val; + + val = 0; + for (bit = 7; p[0] && bit >= 0; ) + { + char c = *p++; + + if (c == ' ') + continue; + + if (c == '1') + val |= (1 << bit); + bit--; + } + sprintf (buf, "%x", val); + monitor_supply_register (HARD_CCR_REGNUM, buf); + } + return 0; +} + static int (* monitor_xfer_memory) (CORE_ADDR, char*, int, int, struct mem_attrib *attrib, struct target_ops*); @@ -636,6 +762,256 @@ return written; } +#define MAP_NOTRANS 0 +#define MAP_CPU16 1 +#define MAP_BANKED 2 +#define MAP_MOT_LINEAR 3 +#define MAP_OFFSET10000 4 + +// converts input address into cannonical (banked) form +unsigned long input_address_translate(int map, unsigned long address) +{ + unsigned long result; + if(map==MAP_NOTRANS) { + return(address); + } else if((map==MAP_BANKED) || (map==MAP_CPU16) ){ + if(address > 0xFFFF) { + return(address); + } else if(address < 0x4000 ) { + return(address); + } else if( address < 0x8000 ) { + return( (address & 0x3FFF) | 0x3E8000 ); + } else if( address < 0xC000 ) { + return( (address & 0x3FFF) | 0x008000 ); + } else { + return( (address & 0x3FFF) | 0x3F8000 ); + } + } else if(map==MAP_MOT_LINEAR) { + result = address & 0x3FFF; + result |= (address << 2) & 0xFF0000; + result += 0x8000; + return(result); + } else if(map==MAP_OFFSET10000) { + if(address <= 0x3FFF) { + return(address); + } else if(address <= 0x7FFF) { + return( (address & 0x3FFF) | 0x3E8000); + } else if(address <= 0xBFFF) { + return( (address & 0x3FFF) | 0x308000); + } else if(address <= 0xFFFF) { + return( (address & 0x3FFF) | 0x3F8000); + } else { + address -= 0x10000; + result = (address & 0x3FFF) | 0x8000; + result |= (address << 2) & 0xFF0000; + return(result); + } + } + return(0); +} + +#define GCC_TO_BANKED(x) input_address_translate(MAP_OFFSET10000, x) + + +unsigned long output_addr_translate(int map, unsigned long address) +{ + + if(map==MAP_NOTRANS) { + return(address); + } else if(map==MAP_CPU16) { + if(address <= 0xFFFF) { + return(address); + } else if((address >= 0x3E8000) && (address <= 0x3EBFFF)) { + return( (address & 0x3FFF) | 0x4000 ); + } else if((address >= 0x3F8000) && (address <= 0x3FBFFF)) { + return( (address & 0x3FFF) | 0xC000 ); + } else { + return(0xFFFFFFFF); + } + + } else if(map==MAP_BANKED) { + return(address); + } else if(map==MAP_MOT_LINEAR) { + if(address <= 0xFFFF) { + return(0xFFFFFFFF); + } else { + return( (address & 0x3FFF) | ((address >> 2) & 0x0FC000)); + } + } else if(map==MAP_OFFSET10000) { + if( address & 0xFF0000) { + return( 0x10000 + ( (address & 0x3FFF) | ((address >> 2) & 0x0FC000))); + } else { + return(address); + } + } else { + fprintf(stderr, "unknown output address map\n"); + return(-1); + } + + #if 0 + return( (address & 0x3FFF) | ((address >> 2) & 0x0FC000)); + #endif +} + + + +static int +dbugS12_insert_breakpoint (CORE_ADDR addr, char *contents_cache) +{ + unsigned long banked; + unsigned char page; + unsigned short offset; + + if(addr <= 0xFFFF) { + printf_filtered("Setting breakpoint: addr=%04X\n", (unsigned int) addr); + monitor_printf("BR %04X\r", (int) addr); + } else { + banked = GCC_TO_BANKED(addr); + page = banked >> 16; + offset = banked & 0xFFFF; + printf_filtered("Setting breakpoint: addr=%06lX, banked=%06lX, page=%02X, offset=%02X\n", addr, banked, page, offset); + monitor_printf("BR %02X:%02X\r", page, offset); + } + monitor_expect_prompt (NULL, 0); + +} + +static int +dbugS12_remove_breakpoint (CORE_ADDR addr, char *contents_cache) +{ + unsigned long banked; + unsigned char page; + unsigned short offset; + + if(addr <= 0xFFFF) { + monitor_printf("BR %04X\r", (int) addr); + } else { + + banked = GCC_TO_BANKED(addr); + page = banked >> 16; + offset = banked & 0xFFFF; + monitor_printf("NOBR %02X:%02X\r", page, offset); + } + monitor_expect_prompt (NULL, 0); + +} + + +static int +dbugS12_xfer_memory (CORE_ADDR memaddr, char *myaddr, int len, int write, + struct mem_attrib *attrib, + struct target_ops *target) +{ + unsigned char val; + int written = 0; + char buf[512]; + int result; + unsigned long banked; + unsigned char page; + unsigned short offset; + unsigned char saved_ppage; + + // NOTE: as written, this will not work across page boundaries + + if (write == 0) { + // read + if(memaddr <= 0xFFFF) { + return monitor_xfer_memory (memaddr, myaddr, len, write, attrib, target); + } + banked = GCC_TO_BANKED(memaddr); + page = banked >> 16; + offset = banked & 0xFFFF; + + // save ppage + dbugS12_dumpregs(); + regcache_collect(HARD_PP_REGNUM, &saved_ppage); + + // set ppage + monitor_printf("pp %02X\r", page); + monitor_expect_prompt (NULL, 0); + + monitor_xfer_memory (offset, myaddr, len, write, attrib, target); + + // restore ppage + monitor_printf("pp %02X\r", saved_ppage); + monitor_expect_prompt (NULL, 0); + + return(len); + } else { + // write + if (len == 0) { + return 0; + } + if(memaddr > 0xFFFF) { + fprintf(stderr, "EROOR: attempt to write flash"); + return(0); + } + /* Enter the sub mode */ + monitor_printf ("mm %x\r", (int) memaddr); + + /* Wait output (7 chars); If we get the prompt, that's too bad. */ + result = monitor_expect (">", buf, 8); + if (result > 0) + return 0; + + while (len) + { + val = *myaddr; + monitor_printf ("%x\r", val); + + result = monitor_expect (">", buf, 8); + if (result > 0) + return written; + + myaddr++; + memaddr++; + written++; + /* If we wanted to, here we could validate the address */ + len--; + } + /* Now exit the sub mode */ + monitor_printf (".\r"); + monitor_expect_prompt (NULL, 0); + return written; + } +} + +static ptid_t +dbugS12_wait (ptid_t ptid, struct target_waitstatus *status) +{ + int length; + char buf[4096]; + printf_filtered("entering dbugS12_wait()\n"); + while(1) { + length = monitor_expect_prompt(buf, sizeof(buf)); + printf_filtered("Wait: %s\n", buf); + if( (length >= 2) && (buf[length-1] == '>') && (buf[length-2] == 'S') ) break; + } + + status->kind = TARGET_WAITKIND_STOPPED; + status->value.sig = TARGET_SIGNAL_TRAP; + + registers_changed (); + dbugS12_dumpregs(); + + printf_filtered("leaving dbugS12_wait()\n"); + + return(ptid); +} + +#ifdef ASYNC +// proceed() won't call ..._wait() after a continue command unless it +// knows gdb and program can run simultaneously. +// Unfortunately, if you set define the wait function, the program will +// be started as soon as gdb loads. +static int +dbugS12_can_async_p (void) +{ + return (0); +} +#endif +// FIXME: dbug for HCS12 probably needs wait and async fixes, too. + static void init_dbug_cmds (void) { @@ -690,12 +1066,161 @@ } static void +init_dbugS12_cmds (void) +{ + dbugS12_cmds.dumpregs = dbugS12_dumpregs; + dbugS12_cmds.flags = MO_NO_ECHO_ON_OPEN | MO_GETMEM_16_BOUNDARY | + MO_SETMEM_INTERACTIVE | + MO_CLR_BREAK_USES_ADDR | MO_GETMEM_NEEDS_RANGE | MO_FILL_USES_ADDR; + dbugS12_cmds.init = dbug_inits; /* Init strings */ + dbugS12_cmds.cont = "g\r"; /* continue command */ + dbugS12_cmds.step = "t 1\r"; /* single step */ + dbugS12_cmds.stop = NULL; /* interrupt command */ + dbugS12_cmds.set_break = "br %x\r"; /* set a breakpoint */ + dbugS12_cmds.clr_break = "nobr %x\r"; /* clear a breakpoint */ + dbugS12_cmds.clr_all_break = "nobr\r"; /* clear all breakpoints */ + dbugS12_cmds.fill = "bf %x %x %x\r"; /* fill (start end val) */ + dbugS12_cmds.setmem.cmdb = "mm %x\r"; /* setmem.cmdb (addr, value) */ + dbugS12_cmds.setmem.cmdw = NULL; + dbugS12_cmds.setmem.cmdl = NULL; + dbugS12_cmds.setmem.cmdll = NULL; /* setmem.cmdll (addr, value) */ + dbugS12_cmds.setmem.resp_delim = NULL; + dbugS12_cmds.setmem.term = NULL; /* setmem.term */ + dbugS12_cmds.setmem.term_cmd = ".\r"; /* setmem.term_cmd */ + dbugS12_cmds.getmem.cmdb = "md %x %x\r"; /* getmem.cmdb (addr, addr2) */ + dbugS12_cmds.getmem.cmdw = NULL; + dbugS12_cmds.getmem.cmdl = NULL; + dbugS12_cmds.getmem.cmdll = NULL; /* getmem.cmdll (addr, addr2) */ + dbugS12_cmds.getmem.resp_delim = " "; /* getmem.resp_delim */ + dbugS12_cmds.getmem.term = NULL; /* getmem.term */ + dbugS12_cmds.getmem.term_cmd = NULL; /* getmem.term_cmd */ + dbugS12_cmds.setreg.cmd = "%s %x\r"; /* setreg.cmd (name, value) */ + dbugS12_cmds.setreg.resp_delim = NULL; + dbugS12_cmds.setreg.term = NULL; /* setreg.term */ + dbugS12_cmds.setreg.term_cmd = NULL; /* setreg.term_cmd */ + dbugS12_cmds.getreg.cmd = NULL; /* getreg.cmd (name) */ + dbugS12_cmds.getreg.resp_delim = " "; /* getreg.resp_delim */ + dbugS12_cmds.getreg.term = NULL; /* getreg.term */ + dbugS12_cmds.getreg.term_cmd = NULL; /* getreg.term_cmd */ + dbugS12_cmds.dump_registers = NULL;; /* dump_registers */ + /* register_pattern */ + dbugS12_cmds.register_pattern = NULL; + dbugS12_cmds.supply_register = NULL; /* supply_register */ + dbugS12_cmds.load_routine = NULL; /* load_routine (defaults to SRECs) */ + dbugS12_cmds.load = "load\r"; /* download command */ + dbugS12_cmds.loadresp = NULL; /* load response */ + dbugS12_cmds.prompt = ">"; /* monitor command prompt */ + dbugS12_cmds.line_term = "\r"; /* end-of-line terminator */ + dbugS12_cmds.cmd_end = NULL; /* optional command terminator */ + dbugS12_cmds.target = &dbugS12_ops; /* target operations */ + dbugS12_cmds.stopbits = SERIAL_2_STOPBITS; /* number of stop bits */ + dbugS12_cmds.regnames = dbugS12_regnames; /* registers names */ + dbugS12_cmds.magic = MONITOR_OPS_MAGIC; /* magic */ +} + +static void dbug_open (char *args, int from_tty) { monitor_open (args, &dbug_cmds, from_tty); set_gdbarch (bfd_arch_m68hc12, 0); } +static void +dbugS12_open (char *args, int from_tty) +{ + struct gdbarch_tdep *tdep_p; + monitor_open (args, &dbugS12_cmds, from_tty); + set_gdbarch (bfd_arch_m68hc12, 0); + #if 0 + // ugly workaround for E_M68HC12_BANKS not being set in elf_flags + // doesn't work because monitor_open dies before we get here + tdep_p = gdbarch_tdep(current_gdbarch); + tdep_p->use_page_register = 1; + set_gdbarch_addr_bit(current_gdbarch, 32); + set_gdbarch_num_regs(current_gdbarch, M68HC12_NUM_REGS); + set_gdbarch_pc_regnum(current_gdbarch, M68HC12_HARD_PC_REGNUM); + set_gdbarch_num_pseudo_regs(current_gdbarch, M68HC12_NUM_PSEUDO_REGS); + #endif +} + +void addrcalc9s12_usage(void) +{ + printf_filtered("unknown input translation\n"); + printf_filtered("usage: \n"); + printf_filtered(" addrcalc9s12 cpu16 4000\n"); + printf_filtered(" addrcalc9s12 banked 3E8000\n"); + printf_filtered(" addrcalc9s12 mot_linear F4000\n"); + printf_filtered(" addrcalc9s12 offset10000 104000\n"); +} + +void +addrcalc9s12( char *args, int from_tty) +{ + unsigned long addr; + char *p; + if(!(args && *args)) { + addrcalc9s12_usage(); + return; + } + p = args; + + if(strncasecmp(args,"cpu16",5)==0) { + p+=5; + addr = strtoul(p, NULL, 16); + addr = input_address_translate(MAP_CPU16, addr); + } else if(strncasecmp(args,"banked", 6)==0) { + p+=6; + addr = strtoul(p, NULL, 16); + addr = input_address_translate(MAP_BANKED, addr); + } else if(strncasecmp(args,"mot_linear",10)==0) { + p+=10; + addr = strtoul(p, NULL, 16); + addr = input_address_translate(MAP_MOT_LINEAR, addr); + } else if(strncasecmp(args,"offset10000",11)==0) { + p+=11; + addr = strtoul(p, NULL, 16); + addr = input_address_translate(MAP_OFFSET10000, addr); + } else { + addrcalc9s12_usage(); + return; + } + + printf_filtered("CPU16: %04lX\n", output_addr_translate(MAP_CPU16, addr)); + printf_filtered("Banked: %06lX\n", output_addr_translate(MAP_BANKED, addr)); + printf_filtered("Motorola Linear:: %05lX\n", output_addr_translate(MAP_MOT_LINEAR, addr)); + printf_filtered("Offset10000: : %06lX\n", output_addr_translate(MAP_OFFSET10000, addr)); + +} +void +wait( char *args, int from_tty) +{ + ptid_t ptid; + struct target_waitstatus status; + + monitor_printf ("\r"); + dbugS12_wait (ptid, &status); + // registers_changed (); + // dbugS12_dumpregs(); + normal_stop(); +} + +/* Pass the command argument through to the bdm12 interface verbatim. The + bdm12 must do any command interpretation work. */ +// taken from remote-bdm12 and modified extensively +void +pass_dbug12_command (char *args, int from_tty) +{ + char buf[1024]; + monitor_printf ("%s\r", args); + monitor_expect_prompt (buf, sizeof(buf)); + + /* Invalidate the register cache, in case the command does + something funny. */ + registers_changed (); + printf_filtered("%s\n", buf); +} + + /* Initialize all 68HC11/68HC12 monitors. */ @@ -720,12 +1245,41 @@ dbug_ops.to_shortname = "dbug"; dbug_ops.to_longname = "DBug monitor"; - dbug_ops.to_doc = "Debug via the DBug 68HC12 monitor.\n\ -Specify the serial device it is connected to (e.g. /dev/ttya)."; + dbug_ops.to_doc = "Debug via the DBug 68HC11 monitor.\n\ +Specify the serial device it is connected to (e.g. /dev/ttya)\n\ +not suitable for 9S12 CPUs."; dbug_ops.to_open = dbug_open; monitor_xfer_memory = dbug_ops.to_xfer_memory; dbug_ops.to_xfer_memory = dbug_xfer_memory; add_target (&dbug_ops); -} + + /* 68HC12 DBug monitor. */ + init_dbugS12_cmds (); + init_monitor_ops (&dbugS12_ops); + + dbugS12_ops.to_shortname = "dbugS12"; + dbugS12_ops.to_longname = "DbugS12 monitor"; + dbugS12_ops.to_doc = "Debug via the DbugS12 68HCS12 monitor.\n\ +Specify the serial device it is connected to (e.g. /dev/ttya).\n\ +Suitable for 9S12 CPUs"; + dbugS12_ops.to_open = dbugS12_open; + monitor_xfer_memory = dbugS12_ops.to_xfer_memory; + dbugS12_ops.to_xfer_memory = dbugS12_xfer_memory; + dbugS12_ops.to_insert_breakpoint = dbugS12_insert_breakpoint; + dbugS12_ops.to_remove_breakpoint = dbugS12_remove_breakpoint; + #ifdef ASYNC + dbugS12_ops.to_wait = dbugS12_wait; /* wait */ + dbugS12_ops.to_can_async_p = dbugS12_can_async_p; + #endif + add_target (&dbugS12_ops); + + add_com ("pod ", class_obscure, pass_dbug12_command, + "Send a command to the BDM interface directly."); + add_com ("addrcalc9s12 ", class_obscure, addrcalc9s12, + "Utility to translate 9S12 addresses"); + add_com ("wait", class_obscure, wait, + "wait for program to stop"); +} + Binary files gdb-6.0.orig/gdb/m68hc11-rom.o and gdb-6.0/gdb/m68hc11-rom.o differ diff -u -r --new-file gdb-6.0.orig/gdb/m68hc11-tdep.c gdb-6.0/gdb/m68hc11-tdep.c --- gdb-6.0.orig/gdb/m68hc11-tdep.c 2003-07-27 17:40:50.000000000 -0400 +++ gdb-6.0/gdb/m68hc11-tdep.c 2005-06-15 19:49:33.000000000 -0400 @@ -43,6 +43,7 @@ #include "opcode/m68hc11.h" #include "elf/m68hc11.h" #include "elf-bfd.h" +#include "m68hc11-tdep.h" /* Macros for setting and testing a bit in a minimal symbol. For 68HC11/68HC12 we have two flags that tell which return @@ -134,33 +135,21 @@ #define M68HC11_REG_SIZE (2) #define M68HC12_NUM_REGS (9) -#define M68HC12_NUM_PSEUDO_REGS ((M68HC11_MAX_SOFT_REGS+5)+1-1) +#define M68HC12_NUM_PSEUDO_REGS ((M68HC11_MAX_SOFT_REGS+5)+1) #define M68HC12_HARD_PC_REGNUM (SOFT_D32_REGNUM+1) -struct insn_sequence; -struct gdbarch_tdep - { - /* Stack pointer correction value. For 68hc11, the stack pointer points - to the next push location. An offset of 1 must be applied to obtain - the address where the last value is saved. For 68hc12, the stack - pointer points to the last value pushed. No offset is necessary. */ - int stack_correction; - - /* Description of instructions in the prologue. */ - struct insn_sequence *prologue; - - /* True if the page memory bank register is available - and must be used. */ - int use_page_register; - - /* ELF flags for ABI. */ - int elf_flags; - }; #define M6811_TDEP gdbarch_tdep (current_gdbarch) #define STACK_CORRECTION (M6811_TDEP->stack_correction) #define USE_PAGE_REGISTER (M6811_TDEP->use_page_register) +#if 0 + // not compatible with offset used by gcc + #define FLASH_OFFSET 0x1000000 +#else + #define FLASH_OFFSET 0x10000 +#endif + struct m68hc11_unwind_cache { /* The previous frame's inner most stack address. Used as this @@ -315,7 +304,7 @@ regcache_cooked_read_unsigned (regcache, HARD_PAGE_REGNUM, &page); pc -= 0x8000; pc += (page << 14); - pc += 0x1000000; + pc += FLASH_OFFSET; } store_unsigned_integer (buf, regsize, pc); return; @@ -351,9 +340,9 @@ memcpy (tmp, buf, regsize); pc = extract_unsigned_integer (tmp, regsize); - if (pc >= 0x1000000) + if (pc >= FLASH_OFFSET) { - pc -= 0x1000000; + pc -= FLASH_OFFSET; regcache_cooked_write_unsigned (regcache, HARD_PAGE_REGNUM, (pc >> 14) & 0x0ff); pc &= 0x03fff; @@ -410,7 +399,6 @@ /* 68HC11 & 68HC12 prologue analysis. */ -#define MAX_CODES 12 /* 68HC11 opcodes. */ #undef M6811_OP_PAGE2 @@ -442,22 +430,7 @@ #define OP_IMM_HIGH (0x300) /* High part of 16-bit constant/address. */ #define OP_PBYTE (0x400) /* 68HC12 indexed operand. */ -/* Identification of the sequence. */ -enum m6811_seq_type -{ - P_LAST = 0, - P_SAVE_REG, /* Save a register on the stack. */ - P_SET_FRAME, /* Setup the frame pointer. */ - P_LOCAL_1, /* Allocate 1 byte for locals. */ - P_LOCAL_2, /* Allocate 2 bytes for locals. */ - P_LOCAL_N /* Allocate N bytes for locals. */ -}; -struct insn_sequence { - enum m6811_seq_type type; - unsigned length; - unsigned short code[MAX_CODES]; -}; /* Sequence of instructions in the 68HC11 function prologue. */ static struct insn_sequence m6811_prologue[] = { @@ -768,6 +741,9 @@ return pc; } + +// FIXME: this function does not appear to return correct value +// if in banked memory static CORE_ADDR m68hc11_unwind_pc (struct gdbarch *gdbarch, struct frame_info *next_frame) { @@ -775,6 +751,7 @@ frame_unwind_unsigned_register (next_frame, gdbarch_pc_regnum (gdbarch), &pc); + printf_unfiltered("m68hc11_unwind_pc(): returning %06lX\n", (long) pc); return pc; } @@ -783,7 +760,8 @@ includes special registers such as pc and fp saved in special ways in the stack frame. sp is even more special: the address we return for it IS the sp for the next frame. */ - +// FIXME: why do we do something totally bizarre (wrong SP) and not +// document why we did it? struct m68hc11_unwind_cache * m68hc11_frame_unwind_cache (struct frame_info *next_frame, void **this_prologue_cache) @@ -949,7 +927,7 @@ 0, &page, 0, 0); *addrp -= 0x08000; *addrp += ((page & 0x0ff) << 14); - *addrp += 0x1000000; + *addrp += FLASH_OFFSET; } } } @@ -1506,6 +1484,9 @@ break; case bfd_arch_m68hc12: + // crude hack -flag isn't being set in ELF file, force it + elf_flags |= E_M68HC12_BANKS; + tdep->stack_correction = 0; tdep->use_page_register = elf_flags & E_M68HC12_BANKS; tdep->prologue = m6812_prologue; @@ -1584,7 +1565,7 @@ frame_unwind_append_predicate (gdbarch, m68hc11_frame_p); frame_base_set_default (gdbarch, &m68hc11_frame_base); - + /* Methods for saving / extracting a dummy frame's ID. The ID's stack address must match the SP value returned by PUSH_DUMMY_CALL, and saved by generic_save_dummy_frame_tos. */ @@ -1616,3 +1597,12 @@ "info registers"); } +/*************************** +After a breakpoint, nexti, next, etc. The gdb bizarrely +calls print_stack_frame() from normal_stop() to print +the current PC location along with file/lineno and function +information. This is bizarre as the current PC is NOT stored +in the current stack frame. + + +***************************/ diff -u -r --new-file gdb-6.0.orig/gdb/m68hc11-tdep.h gdb-6.0/gdb/m68hc11-tdep.h --- gdb-6.0.orig/gdb/m68hc11-tdep.h 1969-12-31 19:00:00.000000000 -0500 +++ gdb-6.0/gdb/m68hc11-tdep.h 2005-01-25 04:17:35.000000000 -0500 @@ -0,0 +1,37 @@ +#define MAX_CODES 12 +/* Identification of the sequence. */ + +enum m6811_seq_type +{ + P_LAST = 0, + P_SAVE_REG, /* Save a register on the stack. */ + P_SET_FRAME, /* Setup the frame pointer. */ + P_LOCAL_1, /* Allocate 1 byte for locals. */ + P_LOCAL_2, /* Allocate 2 bytes for locals. */ + P_LOCAL_N /* Allocate N bytes for locals. */ +}; + +struct insn_sequence { + enum m6811_seq_type type; + unsigned length; + unsigned short code[MAX_CODES]; +}; + +struct gdbarch_tdep + { + /* Stack pointer correction value. For 68hc11, the stack pointer points + to the next push location. An offset of 1 must be applied to obtain + the address where the last value is saved. For 68hc12, the stack + pointer points to the last value pushed. No offset is necessary. */ + int stack_correction; + + /* Description of instructions in the prologue. */ + struct insn_sequence *prologue; + + /* True if the page memory bank register is available + and must be used. */ + int use_page_register; + + /* ELF flags for ABI. */ + int elf_flags; + }; Binary files gdb-6.0.orig/gdb/m68hc11-tdep.o and gdb-6.0/gdb/m68hc11-tdep.o differ diff -u -r --new-file gdb-6.0.orig/gdb/stack.c gdb-6.0/gdb/stack.c --- gdb-6.0.orig/gdb/stack.c 2003-06-11 19:29:47.000000000 -0400 +++ gdb-6.0/gdb/stack.c 2005-06-15 17:33:44.000000000 -0400 @@ -637,7 +637,11 @@ || source == LOC_AND_ADDRESS) { annotate_frame_address (); - ui_out_field_core_addr (uiout, "addr", get_frame_pc (fi)); + #ifndef NO_FRAME_KLUDGE + ui_out_field_core_addr (uiout, "addr", get_frame_pc (fi)); + #else + + #endif annotate_frame_address_end (); ui_out_text (uiout, " in "); } Binary files gdb-6.0.orig/gdb/stack.o and gdb-6.0/gdb/stack.o differ