Tue Jan 21 17:03:26 1997 Geoffrey Noer <noer@cygnus.com>

* mn10300-tdep.c: wrote/fixed implementations of
        mn10300_frame_chain, mn10300_init_extra_frame_info,
        mn10300_frame_saved_pc
        * config/mn10300/tm-mn10300.h: redefine INIT_EXTRA_FRAME_INFO
        and INIT_FRAME_PC macros
        Backtracing starting to work correctly.
This commit is contained in:
Geoffrey Noer 1997-01-22 01:33:58 +00:00
parent ef6c51d13f
commit 95efddf268
3 changed files with 127 additions and 224 deletions

View File

@ -1,3 +1,12 @@
Tue Jan 21 17:03:26 1997 Geoffrey Noer <noer@cygnus.com>
* mn10300-tdep.c: wrote/fixed implementations of
mn10300_frame_chain, mn10300_init_extra_frame_info,
mn10300_frame_saved_pc
* config/mn10300/tm-mn10300.h: redefine INIT_EXTRA_FRAME_INFO
and INIT_FRAME_PC macros
Backtracing starting to work correctly.
Tue Jan 21 17:01:20 1997 Stu Grossman (grossman@lisa.cygnus.com)
* configure.in configure: Check if host has libm. Make sure we

View File

@ -21,13 +21,12 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
#define TARGET_BYTE_ORDER LITTLE_ENDIAN
#define REGISTER_BYTES (NUM_REGS * 4)
#define REGISTER_SIZE 4
#define MAX_REGISTER_RAW_SIZE 4
#define NUM_REGS 14
#define REGISTER_BYTES (NUM_REGS * REGISTER_SIZE)
#define REGISTER_NAMES \
{ "d0", "d1", "d2", "d3", "a0", "a1", "a2", "a3", \
"sp", "pc", "mdr", "psw", "lir", "lar" }
@ -69,6 +68,10 @@ struct value;
#define EXTRA_FRAME_INFO struct frame_saved_regs fsr;
extern void mn10300_init_extra_frame_info PARAMS ((struct frame_info *fi));
#define INIT_EXTRA_FRAME_INFO(fromleaf, fi) mn10300_init_extra_frame_info (fi)
#define INIT_FRAME_PC /* Not necessary */
extern void mn10300_frame_find_saved_regs PARAMS ((struct frame_info *fi, struct frame_saved_regs *regaddr));
#define FRAME_FIND_SAVED_REGS(fi, regaddr) regaddr = fi->fsr

View File

@ -45,202 +45,76 @@ struct prologue_info
struct pifsr *pifsrs;
};
static CORE_ADDR mn10300_scan_prologue PARAMS ((CORE_ADDR pc,
struct prologue_info *fs));
/* Function: scan_prologue
Scan the prologue of the function that contains PC, and record what
we find in PI. PI->fsr must be zeroed by the called. Returns the
pc after the prologue. Note that the addresses saved in pi->fsr
are actually just frame relative (negative offsets from the frame
pointer). This is because we don't know the actual value of the
frame pointer yet. In some circumstances, the frame pointer can't
be determined till after we have scanned the prologue. */
static CORE_ADDR
mn10300_scan_prologue (pc, pi)
CORE_ADDR pc;
struct prologue_info *pi;
{
CORE_ADDR func_addr, prologue_end, current_pc;
struct pifsr *pifsr;
int fp_used;
printf("mn10300_scan_prologue start\n");
/* First, figure out the bounds of the prologue so that we can limit the
search to something reasonable. */
if (find_pc_partial_function (pc, NULL, &func_addr, NULL))
{
struct symtab_and_line sal;
sal = find_pc_line (func_addr, 0);
if (func_addr == entry_point_address ())
pi->start_function = 1;
else
pi->start_function = 0;
#if 0
if (sal.line == 0)
prologue_end = pc;
else
prologue_end = sal.end;
#else
prologue_end = pc;
#endif
}
else
{ /* We're in the boondocks */
func_addr = pc - 100;
prologue_end = pc;
}
prologue_end = min (prologue_end, pc);
/* Now, search the prologue looking for instructions that setup fp, save
rp, adjust sp and such. We also record the frame offset of any saved
registers. */
pi->frameoffset = 0;
pi->framereg = SP_REGNUM;
fp_used = 0;
pifsr = pi->pifsrs;
for (current_pc = func_addr; current_pc < prologue_end; current_pc += 2)
{
int insn;
insn = read_memory_unsigned_integer (current_pc, 2);
if ((insn & 0x07c0) == 0x0780 /* jarl or jr */
|| (insn & 0xffe0) == 0x0060 /* jmp */
|| (insn & 0x0780) == 0x0580) /* branch */
break; /* Ran into end of prologue */
if ((insn & 0xffe0) == ((SP_REGNUM << 11) | 0x0240)) /* add <imm>,sp */
pi->frameoffset = ((insn & 0x1f) ^ 0x10) - 0x10;
else if (insn == ((SP_REGNUM << 11) | 0x0600 | SP_REGNUM)) /* addi <imm>,sp,sp */
pi->frameoffset = read_memory_integer (current_pc + 2, 2);
else if (insn == ((FP_REGNUM << 11) | 0x0000 | 12)) /* mov r12,fp */
{
fp_used = 1;
pi->framereg = FP_REGNUM;
}
else if ((insn & 0x07ff) == (0x0760 | SP_REGNUM) /* st.w <reg>,<offset>[sp] */
|| (fp_used
&& (insn & 0x07ff) == (0x0760 | FP_REGNUM))) /* st.w <reg>,<offset>[fp] */
if (pifsr)
{
pifsr->framereg = insn & 0x1f;
pifsr->reg = (insn >> 11) & 0x1f; /* Extract <reg> */
pifsr->offset = read_memory_integer (current_pc + 2, 2) & ~1;
pifsr++;
}
if ((insn & 0x0780) >= 0x0600) /* Four byte instruction? */
current_pc += 2;
}
if (pifsr)
pifsr->framereg = 0; /* Tie off last entry */
printf("mn10300_scan_prologue end \n");
return current_pc;
}
/* Function: init_extra_frame_info
Setup the frame's frame pointer, pc, and frame addresses for saved
registers. Most of the work is done in scan_prologue().
Note that when we are called for the last frame (currently active frame),
that fi->pc and fi->frame will already be setup. However, fi->frame will
be valid only if this routine uses FP. For previous frames, fi-frame will
always be correct (since that is derived from mn10300_frame_chain ()).
We can be called with the PC in the call dummy under two circumstances.
First, during normal backtracing, second, while figuring out the frame
pointer just prior to calling the target function (see run_stack_dummy). */
void
mn10300_init_extra_frame_info (fi)
struct frame_info *fi;
{
struct prologue_info pi;
struct pifsr pifsrs[NUM_REGS + 1], *pifsr;
int reg;
printf("mn10300_init_extra_frame_info start\n");
if (fi->next)
fi->pc = FRAME_SAVED_PC (fi->next);
memset (fi->fsr.regs, '\000', sizeof fi->fsr.regs);
/* The call dummy doesn't save any registers on the stack, so we can return
now. */
if (PC_IN_CALL_DUMMY (fi->pc, fi->frame, fi->frame))
return;
pi.pifsrs = pifsrs;
mn10300_scan_prologue (fi->pc, &pi);
if (!fi->next && pi.framereg == SP_REGNUM)
fi->frame = read_register (pi.framereg) - pi.frameoffset;
for (pifsr = pifsrs; pifsr->framereg; pifsr++)
{
fi->fsr.regs[pifsr->reg] = pifsr->offset + fi->frame;
if (pifsr->framereg == SP_REGNUM)
fi->fsr.regs[pifsr->reg] += pi.frameoffset;
}
printf("mn10300_init_extra_frame_info end\n");
}
/* Function: frame_chain
Figure out the frame prior to FI. Unfortunately, this involves
scanning the prologue of the caller, which will also be done
shortly by mn10300_init_extra_frame_info. For the dummy frame, we
just return the stack pointer that was in use at the time the
function call was made. */
Figure out and return the caller's frame pointer given current
frame_info struct.
We start out knowing the current pc, current sp, current fp.
We want to determine the caller's fp and caller's pc. To do this
correctly, we have to be able to handle the case where we are in the
middle of the prologue which involves scanning the prologue.
We don't handle dummy frames yet but we would probably just return the
stack pointer that was in use at the time the function call was made?
*/
CORE_ADDR
mn10300_frame_chain (fi)
struct frame_info *fi;
{
struct prologue_info pi;
CORE_ADDR callers_pc, fp;
CORE_ADDR callers_pc, callers_fp, curr_sp;
CORE_ADDR past_prologue_addr;
int past_prologue = 1; /* default to being past prologue */
int n_movm_args = 4;
printf("mn10300_frame_chain start\n");
struct pifsr *pifsr, *pifsr_tmp;
/* First, find out who called us */
callers_pc = FRAME_SAVED_PC (fi);
/* If caller is a call-dummy, then our FP bears no relation to his FP! */
fp = mn10300_find_callers_reg (fi, FP_REGNUM);
if (PC_IN_CALL_DUMMY(callers_pc, fp, fp))
return fp; /* caller is call-dummy: return oldest value of FP */
/* current pc is fi->pc */
/* current fp is fi->frame */
/* Caller is NOT a call-dummy, so everything else should just work.
Even if THIS frame is a call-dummy! */
pi.pifsrs = NULL;
/* current sp is: */
curr_sp = read_register (SP_REGNUM);
mn10300_scan_prologue (callers_pc, &pi);
/*
printf("curr pc = 0x%x ; curr fp = 0x%x ; curr sp = 0x%x\n",
fi->pc, fi->frame, curr_sp);
*/
printf("mn10300_frame_chain end\n");
/* first inst after prologue is: */
past_prologue_addr = mn10300_skip_prologue (fi->pc);
if (pi.start_function)
return 0; /* Don't chain beyond the start function */
/* Are we in the prologue? */
/* Yes if mn10300_skip_prologue returns an address after the
current pc in which case we have to scan prologue */
if (fi->pc < mn10300_skip_prologue (fi->pc))
past_prologue = 0;
if (pi.framereg == FP_REGNUM)
return mn10300_find_callers_reg (fi, pi.framereg);
/* scan prologue if we're not past it */
if (!past_prologue)
{
/* printf("scanning prologue\n"); */
/* FIXME -- fill out this case later */
return 0x666; /* bogus value */
}
return fi->frame - pi.frameoffset;
if (past_prologue) /* if we don't need to scan the prologue */
{
/* printf("we're past the prologue\n"); */
callers_pc = fi->frame - REGISTER_SIZE;
callers_fp = fi->frame - ((n_movm_args + 1) * REGISTER_SIZE);
/*
printf("callers_pc = 0x%x ; callers_fp = 0x%x\n",
callers_pc, callers_fp);
printf("*callers_pc = 0x%x ; *callers_fp = 0x%x\n",
read_memory_integer(callers_pc, REGISTER_SIZE),
read_memory_integer(callers_fp, REGISTER_SIZE));
*/
return read_memory_integer(callers_fp, REGISTER_SIZE);
}
/* we don't get here */
}
/* Function: find_callers_reg
@ -256,7 +130,7 @@ mn10300_find_callers_reg (fi, regnum)
struct frame_info *fi;
int regnum;
{
printf("mn10300_find_callers_reg\n");
/* printf("mn10300_find_callers_reg\n"); */
for (; fi; fi = fi->next)
if (PC_IN_CALL_DUMMY (fi->pc, fi->frame, fi->frame))
@ -269,7 +143,8 @@ mn10300_find_callers_reg (fi, regnum)
}
/* Function: skip_prologue
Return the address of the first code past the prologue of the function. */
Return the address of the first inst past the prologue of the function.
*/
CORE_ADDR
mn10300_skip_prologue (pc)
@ -277,7 +152,7 @@ mn10300_skip_prologue (pc)
{
CORE_ADDR func_addr, func_end;
printf("mn10300_skip_prologue\n");
/* printf("mn10300_skip_prologue\n"); */
/* See what the symbol table says */
@ -310,7 +185,7 @@ mn10300_pop_frame (frame)
{
int regnum;
printf("mn10300_pop_frame start\n");
/* printf("mn10300_pop_frame start\n"); */
if (PC_IN_CALL_DUMMY(frame->pc, frame->frame, frame->frame))
generic_pop_dummy_frame ();
@ -329,7 +204,7 @@ mn10300_pop_frame (frame)
flush_cached_frames ();
printf("mn10300_pop_frame end\n");
/* printf("mn10300_pop_frame end\n"); */
}
/* Function: push_arguments
@ -349,7 +224,7 @@ mn10300_push_arguments (nargs, args, sp, struct_return, struct_addr)
int len = 0;
int stack_offset = 0; /* copy args to this offset onto stack */
printf("mn10300_push_arguments start\n");
/* printf("mn10300_push_arguments start\n"); */
/* First, just for safety, make sure stack is aligned */
sp &= ~3;
@ -390,7 +265,7 @@ mn10300_push_arguments (nargs, args, sp, struct_return, struct_addr)
args++;
}
printf("mn10300_push_arguments end\n");
/* printf"mn10300_push_arguments end\n"); */
return sp;
}
@ -404,7 +279,7 @@ mn10300_push_return_address (pc, sp)
CORE_ADDR pc;
CORE_ADDR sp;
{
printf("mn10300_push_return_address\n");
/* printf("mn10300_push_return_address\n"); */
/* write_register (RP_REGNUM, CALL_DUMMY_ADDRESS ()); */
return sp;
@ -421,13 +296,9 @@ CORE_ADDR
mn10300_frame_saved_pc (fi)
struct frame_info *fi;
{
printf("mn10300_frame_saved_pc\n");
/* printf("mn10300_frame_saved_pc\n"); */
/* if (PC_IN_CALL_DUMMY(fi->pc, fi->frame, fi->frame)) */
return generic_read_register_dummy(fi->pc, fi->frame, PC_REGNUM);
/* else
return mn10300_find_callers_reg (fi, RP_REGNUM);
*/
return (read_memory_integer(fi->frame - REGISTER_SIZE, REGISTER_SIZE));
}
void
@ -439,49 +310,69 @@ get_saved_register (raw_buffer, optimized, addrp, frame, regnum, lval)
int regnum;
enum lval_type *lval;
{
printf("get_saved_register\n");
/* printf("get_saved_register\n"); */
generic_get_saved_register (raw_buffer, optimized, addrp,
frame, regnum, lval);
}
/* Function: fix_call_dummy
Pokes the callee function's address into the CALL_DUMMY assembly stub.
Assumes that the CALL_DUMMY looks like this:
jarl <offset24>, r31
trap
*/
/* Function: init_extra_frame_info
Setup the frame's frame pointer, pc, and frame addresses for saved
registers. Most of the work is done in frame_chain().
int
mn10300_fix_call_dummy (dummy, sp, fun, nargs, args, type, gcc_p)
char *dummy;
CORE_ADDR sp;
CORE_ADDR fun;
int nargs;
value_ptr *args;
struct type *type;
int gcc_p;
Note that when we are called for the last frame (currently active frame),
that fi->pc and fi->frame will already be setup. However, fi->frame will
be valid only if this routine uses FP. For previous frames, fi-frame will
always be correct (since that is derived from v850_frame_chain ()).
We can be called with the PC in the call dummy under two circumstances.
First, during normal backtracing, second, while figuring out the frame
pointer just prior to calling the target function (see run_stack_dummy).
*/
void
mn10300_init_extra_frame_info (fi)
struct frame_info *fi;
{
long offset24;
struct prologue_info pi;
struct pifsr pifsrs[NUM_REGS + 1], *pifsr;
int reg;
printf("mn10300_fix_call_dummy start\n");
if (fi->next)
fi->pc = FRAME_SAVED_PC (fi->next);
offset24 = (long) fun - (long) entry_point_address ();
offset24 &= 0x3fffff;
offset24 |= 0xff800000; /* jarl <offset24>, r31 */
memset (fi->fsr.regs, '\000', sizeof fi->fsr.regs);
store_unsigned_integer ((unsigned int *)&dummy[2], 2, offset24 & 0xffff);
store_unsigned_integer ((unsigned int *)&dummy[0], 2, offset24 >> 16);
/* The call dummy doesn't save any registers on the stack, so we can return
now. */
/*
if (PC_IN_CALL_DUMMY (fi->pc, fi->frame, fi->frame))
return;
printf("mn10300_fix_call_dummy end\n");
pi.pifsrs = pifsrs;
*/
return 0;
/* v850_scan_prologue (fi->pc, &pi); */
/*
if (!fi->next && pi.framereg == SP_REGNUM)
fi->frame = read_register (pi.framereg) - pi.frameoffset;
for (pifsr = pifsrs; pifsr->framereg; pifsr++)
{
fi->fsr.regs[pifsr->reg] = pifsr->offset + fi->frame;
if (pifsr->framereg == SP_REGNUM)
fi->fsr.regs[pifsr->reg] += pi.frameoffset;
}
*/
/* printf("init_extra_frame_info\n"); */
}
void
_initialize_mn10300_tdep ()
{
printf("_initialize_mn10300_tdep\n");
/* printf("_initialize_mn10300_tdep\n"); */
tm_print_insn = print_insn_mn10300;
}