* 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.
This commit is contained in:
Stu Grossman 1996-10-11 22:50:42 +00:00
parent 693e9bf655
commit e5a2ac8b3f
3 changed files with 263 additions and 11 deletions

View File

@ -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 <fnf@cygnus.com>
* dbxread.c (process_one_symbol): Check for null string directly

View File

@ -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 FRAME_SAVED_PC(fi) (read_memory_unsigned_integer((fi)->frame - 4, 4))
#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 */
#define SKIP_PROLOGUE(pc) pc+=8
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
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 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 ())

View File

@ -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 <imm>,sp */
frameoffset = (insn & 0x1f) | ~0x1f;
else if (insn == ((SP_REGNUM << 11) | 0x0600 | SP_REGNUM)) /* addi <imm>,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 <reg>,<offset>[sp] */
{
reg = (insn >> 11) & 0x1f; /* Extract <reg> */
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 <reg>,<offset>[fp] */
{
reg = (insn >> 11) & 0x1f; /* Extract <reg> */
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 <imm>,sp */
frameoffset = (insn & 0x1f) | ~0x1f;
else if (insn == ((SP_REGNUM << 11) | 0x0600 | SP_REGNUM)) /* addi <imm>,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 <reg>,<offset>[sp] */
current_pc += 2;
else if ((insn & 0x07ff) == (0x0760 | FP_REGNUM)) /* st.w <reg>,<offset>[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 ()