From: Stephane Carrez Date: Tue, 13 Aug 2002 16:40:46 +0000 (+0000) Subject: * m68hc11-tdep.c (m68hc11_elf_make_msymbol_special): New function. X-Git-Url: https://git.libre-soc.org/?a=commitdiff_plain;h=7df11f59811c830ac11cbd15a5483c8384dabf87;p=binutils-gdb.git * m68hc11-tdep.c (m68hc11_elf_make_msymbol_special): New function. (m68hc11_gdbarch_init): Install it in gdbarch. (MSYMBOL_SET_RTC, MSYMBOL_SET_RTI): New to set symbol specific flags. (MSYMBOL_IS_RTC, MSYMBOL_IS_RTI): New to test these flags. (MSYMBOL_SIZE): New for documentation. (insn_return_kind): Enum to specify how a function returns. (frame_extra_info): Cleanup and record the return mode. (gdbarch_tdep, USE_PAGE_REGISTER): New to control the use of page register in address computation. (m68hc11_get_return_insn): New to obtain the return instruction used by the function. (m68hc11_frame_init_saved_regs): Take into account the return instruction used by the function for far and interrupt functions. (m68hc11_init_extra_frame_info): Take into account page register. (m68hc11_frame_args_address): Adjust according to the return mode. (show_regs): Print page register only when it's used. --- diff --git a/gdb/ChangeLog b/gdb/ChangeLog index f66f2943742..90f6ec4f2f0 100644 --- a/gdb/ChangeLog +++ b/gdb/ChangeLog @@ -1,3 +1,22 @@ +2002-08-13 Stephane Carrez + + * m68hc11-tdep.c (m68hc11_elf_make_msymbol_special): New function. + (m68hc11_gdbarch_init): Install it in gdbarch. + (MSYMBOL_SET_RTC, MSYMBOL_SET_RTI): New to set symbol specific flags. + (MSYMBOL_IS_RTC, MSYMBOL_IS_RTI): New to test these flags. + (MSYMBOL_SIZE): New for documentation. + (insn_return_kind): Enum to specify how a function returns. + (frame_extra_info): Cleanup and record the return mode. + (gdbarch_tdep, USE_PAGE_REGISTER): New to control the use of page + register in address computation. + (m68hc11_get_return_insn): New to obtain the return instruction used + by the function. + (m68hc11_frame_init_saved_regs): Take into account the return + instruction used by the function for far and interrupt functions. + (m68hc11_init_extra_frame_info): Take into account page register. + (m68hc11_frame_args_address): Adjust according to the return mode. + (show_regs): Print page register only when it's used. + 2002-08-13 Stephane Carrez * m68hc11-tdep.c (HARD_PAGE_REGNUM): Define for 68HC12 page register. diff --git a/gdb/m68hc11-tdep.c b/gdb/m68hc11-tdep.c index c2f7a4bbf76..0ad7c9dcde1 100644 --- a/gdb/m68hc11-tdep.c +++ b/gdb/m68hc11-tdep.c @@ -39,6 +39,47 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #include "elf/m68hc11.h" #include "elf-bfd.h" +/* Macros for setting and testing a bit in a minimal symbol. + For 68HC11/68HC12 we have two flags that tell which return + type the function is using. This is used for prologue and frame + analysis to compute correct stack frame layout. + + The MSB of the minimal symbol's "info" field is used for this purpose. + This field is already being used to store the symbol size, so the + assumption is that the symbol size cannot exceed 2^30. + + MSYMBOL_SET_RTC Actually sets the "RTC" bit. + MSYMBOL_SET_RTI Actually sets the "RTI" bit. + MSYMBOL_IS_RTC Tests the "RTC" bit in a minimal symbol. + MSYMBOL_IS_RTI Tests the "RTC" bit in a minimal symbol. + MSYMBOL_SIZE Returns the size of the minimal symbol, + i.e. the "info" field with the "special" bit + masked out. */ + +#define MSYMBOL_SET_RTC(msym) \ + MSYMBOL_INFO (msym) = (char *) (((long) MSYMBOL_INFO (msym)) \ + | 0x80000000) + +#define MSYMBOL_SET_RTI(msym) \ + MSYMBOL_INFO (msym) = (char *) (((long) MSYMBOL_INFO (msym)) \ + | 0x40000000) + +#define MSYMBOL_IS_RTC(msym) \ + (((long) MSYMBOL_INFO (msym) & 0x80000000) != 0) + +#define MSYMBOL_IS_RTI(msym) \ + (((long) MSYMBOL_INFO (msym) & 0x40000000) != 0) + +#define MSYMBOL_SIZE(msym) \ + ((long) MSYMBOL_INFO (msym) & 0x3fffffff) + +enum insn_return_kind { + RETURN_RTS, + RETURN_RTC, + RETURN_RTI +}; + + /* Register numbers of various important registers. Note that some of these values are "real" register numbers, and correspond to the general registers of the machine, @@ -99,20 +140,24 @@ struct gdbarch_tdep /* 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) struct frame_extra_info { - int frame_reg; CORE_ADDR return_pc; - CORE_ADDR dummy; int frameless; int size; + enum insn_return_kind return_kind; }; /* Table of registers for 68HC11. This includes the hard registers @@ -313,7 +358,15 @@ m68hc11_frame_saved_pc (struct frame_info *frame) static CORE_ADDR m68hc11_frame_args_address (struct frame_info *frame) { - return frame->frame + frame->extra_info->size + STACK_CORRECTION + 2; + CORE_ADDR addr; + + addr = frame->frame + frame->extra_info->size + STACK_CORRECTION + 2; + if (frame->extra_info->return_kind == RETURN_RTC) + addr += 1; + else if (frame->extra_info->return_kind == RETURN_RTI) + addr += 7; + + return addr; } static CORE_ADDR @@ -528,6 +581,28 @@ m68hc11_analyze_instruction (struct insn_sequence *seq, CORE_ADDR *pc, return 0; } +/* Return the instruction that the function at the PC is using. */ +static enum insn_return_kind +m68hc11_get_return_insn (CORE_ADDR pc) +{ + struct minimal_symbol *sym; + + /* A flag indicating that this is a STO_M68HC12_FAR or STO_M68HC12_INTERRUPT + function is stored by elfread.c in the high bit of the info field. + Use this to decide which instruction the function uses to return. */ + sym = lookup_minimal_symbol_by_pc (pc); + if (sym == 0) + return RETURN_RTS; + + if (MSYMBOL_IS_RTC (sym)) + return RETURN_RTC; + else if (MSYMBOL_IS_RTI (sym)) + return RETURN_RTI; + else + return RETURN_RTS; +} + + /* Analyze the function prologue to find some information about the function: - the PC of the first line (for m68hc11_skip_prologue) @@ -715,19 +790,35 @@ m68hc11_frame_init_saved_regs (struct frame_info *fi) { CORE_ADDR pc; CORE_ADDR addr; - + if (fi->saved_regs == NULL) frame_saved_regs_zalloc (fi); else memset (fi->saved_regs, 0, sizeof (fi->saved_regs)); pc = fi->pc; + fi->extra_info->return_kind = m68hc11_get_return_insn (pc); m68hc11_guess_from_prologue (pc, fi->frame, &pc, &fi->extra_info->size, fi->saved_regs); addr = fi->frame + fi->extra_info->size + STACK_CORRECTION; if (soft_regs[SOFT_FP_REGNUM].name) fi->saved_regs[SOFT_FP_REGNUM] = addr - 2; + + /* Take into account how the function was called/returns. */ + if (fi->extra_info->return_kind == RETURN_RTC) + { + fi->saved_regs[HARD_PAGE_REGNUM] = addr; + addr++; + } + else if (fi->extra_info->return_kind == RETURN_RTI) + { + fi->saved_regs[HARD_CCR_REGNUM] = addr; + fi->saved_regs[HARD_D_REGNUM] = addr + 1; + fi->saved_regs[HARD_X_REGNUM] = addr + 3; + fi->saved_regs[HARD_Y_REGNUM] = addr + 5; + addr += 7; + } fi->saved_regs[HARD_SP_REGNUM] = addr; fi->saved_regs[HARD_PC_REGNUM] = fi->saved_regs[HARD_SP_REGNUM]; } @@ -747,20 +838,27 @@ m68hc11_init_extra_frame_info (int fromleaf, struct frame_info *fi) if (fromleaf) { + fi->extra_info->return_kind = m68hc11_get_return_insn (fi->pc); fi->extra_info->return_pc = m68hc11_saved_pc_after_call (fi); } else { - addr = fi->frame + fi->extra_info->size + STACK_CORRECTION; + addr = fi->saved_regs[HARD_PC_REGNUM]; addr = read_memory_unsigned_integer (addr, 2) & 0x0ffff; + + /* Take into account the 68HC12 specific call (PC + page). */ + if (fi->extra_info->return_kind == RETURN_RTC + && addr >= 0x08000 && addr < 0x0c000 + && USE_PAGE_REGISTER) + { + CORE_ADDR page_addr = fi->saved_regs[HARD_PAGE_REGNUM]; + + unsigned page = read_memory_unsigned_integer (page_addr, 1); + addr -= 0x08000; + addr += ((page & 0x0ff) << 14); + addr += 0x1000000; + } fi->extra_info->return_pc = addr; -#if 0 - printf ("Pc@0x%04x, FR 0x%04x, size %d, read ret @0x%04x -> 0x%04x\n", - fi->pc, - fi->frame, fi->size, - addr & 0x0ffff, - fi->return_pc); -#endif } } @@ -786,11 +884,18 @@ show_regs (char *args, int from_tty) ccr & M6811_V_BIT ? 'V' : '-', ccr & M6811_C_BIT ? 'C' : '-'); - printf_filtered ("D=%04x IX=%04x IY=%04x\n", + printf_filtered ("D=%04x IX=%04x IY=%04x", (int) read_register (HARD_D_REGNUM), (int) read_register (HARD_X_REGNUM), (int) read_register (HARD_Y_REGNUM)); + if (USE_PAGE_REGISTER) + { + printf_filtered (" Page=%02x", + (int) read_register (HARD_PAGE_REGNUM)); + } + printf_filtered ("\n"); + nr = 0; for (i = SOFT_D1_REGNUM; i < M68HC11_ALL_REGS; i++) { @@ -1044,6 +1149,21 @@ m68hc11_register_raw_size (int reg_nr) } } +/* Test whether the ELF symbol corresponds to a function using rtc or + rti to return. */ + +static void +m68hc11_elf_make_msymbol_special (asymbol *sym, struct minimal_symbol *msym) +{ + unsigned char flags; + + flags = ((elf_symbol_type *)sym)->internal_elf_sym.st_other; + if (flags & STO_M68HC12_FAR) + MSYMBOL_SET_RTC (msym); + if (flags & STO_M68HC12_INTERRUPT) + MSYMBOL_SET_RTI (msym); +} + static int gdb_print_insn_m68hc11 (bfd_vma memaddr, disassemble_info *info) { @@ -1092,11 +1212,13 @@ m68hc11_gdbarch_init (struct gdbarch_info info, { case bfd_arch_m68hc11: tdep->stack_correction = 1; + tdep->use_page_register = 0; tdep->prologue = m6811_prologue; break; case bfd_arch_m68hc12: tdep->stack_correction = 0; + tdep->use_page_register = elf_flags & E_M68HC12_BANKS; tdep->prologue = m6812_prologue; break; @@ -1198,6 +1320,10 @@ m68hc11_gdbarch_init (struct gdbarch_info info, set_gdbarch_stack_align (gdbarch, m68hc11_stack_align); set_gdbarch_print_insn (gdbarch, gdb_print_insn_m68hc11); + /* Minsymbol frobbing. */ + set_gdbarch_elf_make_msymbol_special (gdbarch, + m68hc11_elf_make_msymbol_special); + set_gdbarch_believe_pcc_promotion (gdbarch, 1); return gdbarch;