From e5a2ac8b3f597f5d7f24f592dc897118a1e106ec Mon Sep 17 00:00:00 2001 From: Stu Grossman Date: Fri, 11 Oct 1996 22:50:42 +0000 Subject: [PATCH] * frame.h: Move definition of struct frame_saved_args to before struct frame to make it possible to use frame_saved_args in EXTRA_FRAME_INFO macro. * v850-tdep.c config/v850/tm-v850.h: Lotsa new functions and macros to make frame operations (such as backtrace) work. --- gdb/ChangeLog | 11 ++ gdb/config/v850/tm-v850.h | 47 +++++++-- gdb/v850-tdep.c | 216 ++++++++++++++++++++++++++++++++++++++ 3 files changed, 263 insertions(+), 11 deletions(-) diff --git a/gdb/ChangeLog b/gdb/ChangeLog index c0b1a5b3174..32d8af27cb2 100644 --- a/gdb/ChangeLog +++ b/gdb/ChangeLog @@ -1,3 +1,14 @@ +Fri Oct 11 15:43:54 1996 Stu Grossman (grossman@critters.cygnus.com) + + * frame.h: Move definition of struct frame_saved_args to before + struct frame to make it possible to use frame_saved_args in + EXTRA_FRAME_INFO macro. + +start-sanitize-v850 + * v850-tdep.c config/v850/tm-v850.h: Lotsa new functions and + macros to make frame operations (such as backtrace) work. + +end-sanitize-v850 Fri Oct 11 14:23:50 1996 Fred Fish * dbxread.c (process_one_symbol): Check for null string directly diff --git a/gdb/config/v850/tm-v850.h b/gdb/config/v850/tm-v850.h index b09b25a6d36..5aa11b56962 100644 --- a/gdb/config/v850/tm-v850.h +++ b/gdb/config/v850/tm-v850.h @@ -41,6 +41,8 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #define SP_REGNUM 3 #define FP_REGNUM 2 +#define V0_REGNUM 10 +#define V1_REGNUM 11 #define RP_REGNUM 31 #define PC_REGNUM 64 @@ -58,26 +60,49 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #define DECR_PC_AFTER_BREAK 0 -#define POP_FRAME warning ("POP_FRAME not implemented yet!") - #define INNER_THAN < -#define FRAME_ARGS_SKIP 4 - #define SAVED_PC_AFTER_CALL(fi) read_register (RP_REGNUM) -#define FRAME_CHAIN(fi) (read_memory_unsigned_integer ((fi)->frame - 8, 4)) +#ifdef __STDC__ +struct frame_info; +struct frame_saved_regs; +struct type; +#endif + +#define EXTRA_FRAME_INFO struct frame_saved_regs fsr; + +extern void v850_init_extra_frame_info PARAMS ((struct frame_info *fi)); +#define INIT_EXTRA_FRAME_INFO(fromleaf, fi) v850_init_extra_frame_info (fi) +#define INIT_FRAME_PC /* Not necessary */ + +extern void v850_frame_find_saved_regs PARAMS ((struct frame_info *fi, struct frame_saved_regs *regaddr)); +#define FRAME_FIND_SAVED_REGS(fi, regaddr) regaddr = fi->fsr -#define FRAME_SAVED_PC(fi) (read_memory_unsigned_integer((fi)->frame - 4, 4)) +extern CORE_ADDR v850_frame_chain PARAMS ((struct frame_info *fi)); +#define FRAME_CHAIN(fi) v850_frame_chain (fi) +extern CORE_ADDR v850_find_callers_reg PARAMS ((struct frame_info *fi, int regnum)); +#define FRAME_SAVED_PC(fi) (v850_find_callers_reg (fi, RP_REGNUM)) -#define SKIP_PROLOGUE(pc) pc+=8 +#define EXTRACT_RETURN_VALUE(TYPE, REGBUF, VALBUF) \ + memcpy (VALBUF, REGBUF + REGISTER_BYTE (V0_REGNUM), TYPE_LENGTH (TYPE)) + +#define EXTRACT_STRUCT_VALUE_ADDRESS(REGBUF) \ + (extract_address (REGBUF + REGISTER_BYTE (V0_REGNUM), \ + REGISTER_RAW_SIZE (V0_REGNUM))) + +#define STORE_RETURN_VALUE(TYPE, VALBUF) \ + write_register_bytes(REGISTER_BYTE (V0_REGNUM), VALBUF, TYPE_LENGTH (TYPE)); + +extern CORE_ADDR v850_skip_prologue PARAMS ((CORE_ADDR pc)); +#define SKIP_PROLOGUE(pc) pc = v850_skip_prologue (pc) + +#define FRAME_ARGS_SKIP 0 #define FRAME_ARGS_ADDRESS(fi) ((fi)->frame) #define FRAME_LOCALS_ADDRESS(fi) ((fi)->frame) #define FRAME_NUM_ARGS(val, fi) ((val) = -1) -#define FRAME_FIND_SAVED_REGS(fi, regaddr) warning ("FRAME_FIND_SAVED_REGS not implemented yet!") - -#define EXTRACT_RETURN_VALUE(TYPE, REGBUF, VALBUF) warning ("EXTRACT_RETURN_VALUE not implemented yet!") -#define STORE_RETURN_VALUE(TYPE, VALBUF) warning ("STORE_RETURN_VALUE not implemented yet!") +extern struct frame_info *v850_pop_frame PARAMS ((struct frame_info *frame)); +#define POP_FRAME v850_pop_frame (get_current_frame ()) diff --git a/gdb/v850-tdep.c b/gdb/v850-tdep.c index b710920942e..7363fc2e528 100644 --- a/gdb/v850-tdep.c +++ b/gdb/v850-tdep.c @@ -30,6 +30,222 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #include "gdb_string.h" #include "gdbcore.h" + + +/* This function actually figures out the frame address for a given pc and + sp. This is tricky on the v850 because we only use an explicit frame + pointer when using alloca(). The only reliable way to get this info is to + examine the prologue. +*/ + +void +v850_init_extra_frame_info (fi) + struct frame_info *fi; +{ + struct symtab_and_line sal; + CORE_ADDR func_addr, prologue_end, current_pc; + int reg; + int frameoffset; + int framereg; + + if (fi->next) + fi->pc = v850_find_callers_reg (fi->next, RP_REGNUM); + + /* First, figure out the bounds of the prologue so that we can limit the + search to something reasonable. */ + + if (find_pc_partial_function (fi->pc, NULL, &func_addr, NULL)) + { + sal = find_pc_line (func_addr, 0); + + prologue_end = sal.end; + } + else + prologue_end = func_addr + 100; /* We're in the boondocks */ + + prologue_end = min (prologue_end, fi->pc); + + /* Now, search the prologue looking for instructions that setup fp, save + rp, adjust sp and such. */ + + framereg = SP_REGNUM; + frameoffset = 0; + memset (fi->fsr.regs, '\000', sizeof fi->fsr.regs); + + for (current_pc = func_addr; current_pc < prologue_end; current_pc += 2) + { + int insn; + + insn = read_memory_integer (current_pc, 2); + + if ((insn & 0xffe0) == ((SP_REGNUM << 11) | 0x0240)) /* add ,sp */ + frameoffset = (insn & 0x1f) | ~0x1f; + else if (insn == ((SP_REGNUM << 11) | 0x0600 | SP_REGNUM)) /* addi ,sp,sp */ + { + current_pc += 2; + + frameoffset = read_memory_integer (current_pc, 2); + } + else if (insn == ((FP_REGNUM << 11) | 0x0000 | 12)) /* mov r12,r2 */ + framereg = FP_REGNUM; /* Setting up fp */ + else if ((insn & 0x07ff) == (0x0760 | SP_REGNUM)) /* st.w ,[sp] */ + { + reg = (insn >> 11) & 0x1f; /* Extract */ + current_pc += 2; + + insn = read_memory_integer (current_pc, 2) & ~1; + + fi->fsr.regs[reg] = insn + frameoffset; + } + else if ((insn & 0x07ff) == (0x0760 | FP_REGNUM)) /* st.w ,[fp] */ + { + reg = (insn >> 11) & 0x1f; /* Extract */ + current_pc += 2; + + insn = read_memory_integer (current_pc, 2) & ~1; + + fi->fsr.regs[reg] = insn; + } + } + +#if 0 + if (!fi->next) + fi->frame = read_register (framereg); + else + if (framereg == SP_REGNUM) + fi->frame = fi->next->frame; + else + fi->frame = v850_find_callers_reg (fi, framereg); + + if (framereg == SP_REGNUM) + fi->frame -= frameoffset; +#else + if (!fi->next && framereg == SP_REGNUM) + fi->frame = read_register (framereg) - frameoffset; +#endif + + for (reg = 0; reg < NUM_REGS; reg++) + if (fi->fsr.regs[reg] != 0) + fi->fsr.regs[reg] += fi->frame; +} + +/* Find the caller of this frame. We do this by seeing if RP_REGNUM is saved + in the stack anywhere, otherwise we get it from the registers. */ + +CORE_ADDR +v850_find_callers_reg (fi, regnum) + struct frame_info *fi; + int regnum; +{ + for (; fi; fi = fi->next) + if (fi->fsr.regs[regnum] != 0) + return read_memory_integer (fi->fsr.regs[regnum], 4); + + return read_register (regnum); +} + +CORE_ADDR +v850_frame_chain (fi) + struct frame_info *fi; +{ + CORE_ADDR callers_pc, callers_sp; + struct frame_info temp_fi; + CORE_ADDR func_addr, prologue_end, current_pc; + int frameoffset; + + /* First, find out who called us */ + + callers_pc = v850_find_callers_reg (fi, RP_REGNUM); + + /* Next, figure out where his prologue is. */ + + if (find_pc_partial_function (callers_pc, NULL, &func_addr, NULL)) + { + struct symtab_and_line sal; + + sal = find_pc_line (func_addr, 0); + + prologue_end = sal.end; + } + else + prologue_end = func_addr + 100; /* We're in the boondocks */ + + prologue_end = min (prologue_end, callers_pc); + + /* Now, figure out the frame location of the caller by examining his prologue. + We're looking for either a load of the frame pointer register, or a stack + adjustment. */ + + frameoffset = 0; + + for (current_pc = func_addr; current_pc < prologue_end; current_pc += 2) + { + int insn; + + insn = read_memory_integer (current_pc, 2); + + if ((insn & 0xffe0) == ((SP_REGNUM << 11) | 0x0240)) /* add ,sp */ + frameoffset = (insn & 0x1f) | ~0x1f; + else if (insn == ((SP_REGNUM << 11) | 0x0600 | SP_REGNUM)) /* addi ,sp,sp */ + { + current_pc += 2; + + frameoffset = read_memory_integer (current_pc, 2); + } + else if (insn == ((FP_REGNUM << 11) | 0x0000 | 12)) /* mov r12,r2 */ + return v850_find_callers_reg (fi, FP_REGNUM); /* It's using a frame pointer reg */ + else if ((insn & 0x07ff) == (0x0760 | SP_REGNUM)) /* st.w ,[sp] */ + current_pc += 2; + else if ((insn & 0x07ff) == (0x0760 | FP_REGNUM)) /* st.w ,[fp] */ + current_pc += 2; + } + + return fi->frame - frameoffset; +} + +CORE_ADDR +v850_skip_prologue (pc) + CORE_ADDR pc; +{ + CORE_ADDR func_addr, func_end; + + /* See what the symbol table says */ + + if (find_pc_partial_function (pc, NULL, &func_addr, &func_end)) + { + struct symtab_and_line sal; + + sal = find_pc_line (func_addr, 0); + + if (sal.end < func_end) + return sal.end; + else + /* The line after the prologue is after the end of the function. In + this case, there probably isn't a prologue. */ + return pc; + } + +/* We can't find the start of this function, so there's nothing we can do. */ + return pc; +} + +struct frame_info * +v850_pop_frame (frame) + struct frame_info *frame; +{ + int regnum; + + write_register (PC_REGNUM, FRAME_SAVED_PC (frame)); + + for (regnum = 0; regnum < NUM_REGS; regnum++) + if (frame->fsr.regs[regnum] != 0) + write_register (regnum, read_memory_integer (frame->fsr.regs[regnum], 4)); + + write_register (SP_REGNUM, FRAME_FP (frame)); + flush_cached_frames (); + + return NULL; +} void _initialize_sparc_tdep () -- 2.30.2