* m68hc11-tdep.c (struct m68hc11_unwind_cache): New struct to hold
frame unwind information. (m68hc11_scan_prologue): New function from m68hc11_guess_from_prologue and adapted for frame unwinding. (m68hc11_skip_prologue): Update to scan prologue in temporary object. (m68hc11_unwind_pc): New function. (m68hc11_frame_unwind_cache): New function to analyze frames. (m68hc11_frame_this_id): New function to create new frame struct. (m68hc11_frame_prev_register): New function to unwind a register from the frame. (m68hc11_frame_unwind): Default 68hc11/68hc12 unwinder. (m68hc11_frame_p): New function for the above. (m68hc11_frame_base_address): New function to return fp of frame. (m68hc11_frame_args_address): Update for frame. (m68hc11_frame_base): Default 68hc11/68hc12 frame. (m68hc11_unwind_sp): New function. (m68hc11_unwind_dummy_id): New function. (m68hc11_gdbarch_init): Install the above frames; remove deprecated calls.
This commit is contained in:
parent
225f2bf663
commit
1ea653ae0a
|
@ -1,3 +1,25 @@
|
||||||
|
2003-07-27 Stephane Carrez <stcarrez@nerim.fr>
|
||||||
|
|
||||||
|
* m68hc11-tdep.c (struct m68hc11_unwind_cache): New struct to hold
|
||||||
|
frame unwind information.
|
||||||
|
(m68hc11_scan_prologue): New function from m68hc11_guess_from_prologue
|
||||||
|
and adapted for frame unwinding.
|
||||||
|
(m68hc11_skip_prologue): Update to scan prologue in temporary object.
|
||||||
|
(m68hc11_unwind_pc): New function.
|
||||||
|
(m68hc11_frame_unwind_cache): New function to analyze frames.
|
||||||
|
(m68hc11_frame_this_id): New function to create new frame struct.
|
||||||
|
(m68hc11_frame_prev_register): New function to unwind a register from
|
||||||
|
the frame.
|
||||||
|
(m68hc11_frame_unwind): Default 68hc11/68hc12 unwinder.
|
||||||
|
(m68hc11_frame_p): New function for the above.
|
||||||
|
(m68hc11_frame_base_address): New function to return fp of frame.
|
||||||
|
(m68hc11_frame_args_address): Update for frame.
|
||||||
|
(m68hc11_frame_base): Default 68hc11/68hc12 frame.
|
||||||
|
(m68hc11_unwind_sp): New function.
|
||||||
|
(m68hc11_unwind_dummy_id): New function.
|
||||||
|
(m68hc11_gdbarch_init): Install the above frames; remove deprecated
|
||||||
|
calls.
|
||||||
|
|
||||||
2003-07-27 Stephane Carrez <stcarrez@nerim.fr>
|
2003-07-27 Stephane Carrez <stcarrez@nerim.fr>
|
||||||
|
|
||||||
* m68hc11-tdep.c (m68hc11_analyze_instruction): Don't advance the pc.
|
* m68hc11-tdep.c (m68hc11_analyze_instruction): Don't advance the pc.
|
||||||
|
|
|
@ -21,6 +21,10 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
|
||||||
|
|
||||||
#include "defs.h"
|
#include "defs.h"
|
||||||
#include "frame.h"
|
#include "frame.h"
|
||||||
|
#include "frame-unwind.h"
|
||||||
|
#include "frame-base.h"
|
||||||
|
#include "dwarf2-frame.h"
|
||||||
|
#include "trad-frame.h"
|
||||||
#include "symtab.h"
|
#include "symtab.h"
|
||||||
#include "gdbtypes.h"
|
#include "gdbtypes.h"
|
||||||
#include "gdbcmd.h"
|
#include "gdbcmd.h"
|
||||||
|
@ -157,6 +161,25 @@ struct gdbarch_tdep
|
||||||
#define STACK_CORRECTION (M6811_TDEP->stack_correction)
|
#define STACK_CORRECTION (M6811_TDEP->stack_correction)
|
||||||
#define USE_PAGE_REGISTER (M6811_TDEP->use_page_register)
|
#define USE_PAGE_REGISTER (M6811_TDEP->use_page_register)
|
||||||
|
|
||||||
|
struct m68hc11_unwind_cache
|
||||||
|
{
|
||||||
|
/* The previous frame's inner most stack address. Used as this
|
||||||
|
frame ID's stack_addr. */
|
||||||
|
CORE_ADDR prev_sp;
|
||||||
|
/* The frame's base, optionally used by the high-level debug info. */
|
||||||
|
CORE_ADDR base;
|
||||||
|
CORE_ADDR pc;
|
||||||
|
int size;
|
||||||
|
int prologue_type;
|
||||||
|
CORE_ADDR return_pc;
|
||||||
|
CORE_ADDR sp_offset;
|
||||||
|
int frameless;
|
||||||
|
enum insn_return_kind return_kind;
|
||||||
|
|
||||||
|
/* Table indicating the location of each and every register. */
|
||||||
|
struct trad_frame_saved_reg *saved_regs;
|
||||||
|
};
|
||||||
|
|
||||||
struct frame_extra_info
|
struct frame_extra_info
|
||||||
{
|
{
|
||||||
CORE_ADDR return_pc;
|
CORE_ADDR return_pc;
|
||||||
|
@ -412,20 +435,6 @@ m68hc11_frame_saved_pc (struct frame_info *frame)
|
||||||
return get_frame_extra_info (frame)->return_pc;
|
return get_frame_extra_info (frame)->return_pc;
|
||||||
}
|
}
|
||||||
|
|
||||||
static CORE_ADDR
|
|
||||||
m68hc11_frame_args_address (struct frame_info *frame)
|
|
||||||
{
|
|
||||||
CORE_ADDR addr;
|
|
||||||
|
|
||||||
addr = get_frame_base (frame) + get_frame_extra_info (frame)->size + STACK_CORRECTION + 2;
|
|
||||||
if (get_frame_extra_info (frame)->return_kind == RETURN_RTC)
|
|
||||||
addr += 1;
|
|
||||||
else if (get_frame_extra_info (frame)->return_kind == RETURN_RTI)
|
|
||||||
addr += 7;
|
|
||||||
|
|
||||||
return addr;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Discard from the stack the innermost frame, restoring all saved
|
/* Discard from the stack the innermost frame, restoring all saved
|
||||||
registers. */
|
registers. */
|
||||||
|
|
||||||
|
@ -660,35 +669,35 @@ m68hc11_get_return_insn (CORE_ADDR pc)
|
||||||
return RETURN_RTS;
|
return RETURN_RTS;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/* Analyze the function prologue to find some information
|
/* Analyze the function prologue to find some information
|
||||||
about the function:
|
about the function:
|
||||||
- the PC of the first line (for m68hc11_skip_prologue)
|
- the PC of the first line (for m68hc11_skip_prologue)
|
||||||
- the offset of the previous frame saved address (from current frame)
|
- the offset of the previous frame saved address (from current frame)
|
||||||
- the soft registers which are pushed. */
|
- the soft registers which are pushed. */
|
||||||
static void
|
static CORE_ADDR
|
||||||
m68hc11_guess_from_prologue (CORE_ADDR pc, CORE_ADDR current_pc, CORE_ADDR fp,
|
m68hc11_scan_prologue (CORE_ADDR pc, CORE_ADDR current_pc,
|
||||||
CORE_ADDR *first_line,
|
struct m68hc11_unwind_cache *info)
|
||||||
int *frame_offset, CORE_ADDR *pushed_regs)
|
|
||||||
{
|
{
|
||||||
CORE_ADDR save_addr;
|
LONGEST save_addr;
|
||||||
CORE_ADDR func_end;
|
CORE_ADDR func_end;
|
||||||
int size;
|
int size;
|
||||||
int found_frame_point;
|
int found_frame_point;
|
||||||
int saved_reg;
|
int saved_reg;
|
||||||
CORE_ADDR first_pc;
|
|
||||||
int done = 0;
|
int done = 0;
|
||||||
struct insn_sequence *seq_table;
|
struct insn_sequence *seq_table;
|
||||||
|
|
||||||
first_pc = get_pc_function_start (pc);
|
info->size = 0;
|
||||||
|
info->sp_offset = 0;
|
||||||
|
if (pc >= current_pc)
|
||||||
|
return current_pc;
|
||||||
|
|
||||||
size = 0;
|
size = 0;
|
||||||
|
|
||||||
m68hc11_initialize_register_info ();
|
m68hc11_initialize_register_info ();
|
||||||
if (first_pc == 0)
|
if (pc == 0)
|
||||||
{
|
{
|
||||||
*frame_offset = 0;
|
info->size = 0;
|
||||||
*first_line = pc;
|
return pc;
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
seq_table = gdbarch_tdep (current_gdbarch)->prologue;
|
seq_table = gdbarch_tdep (current_gdbarch)->prologue;
|
||||||
|
@ -734,16 +743,15 @@ m68hc11_guess_from_prologue (CORE_ADDR pc, CORE_ADDR current_pc, CORE_ADDR fp,
|
||||||
we find an instruction which is not supposed to appear in the
|
we find an instruction which is not supposed to appear in the
|
||||||
prologue (as generated by gcc 2.95, 2.96).
|
prologue (as generated by gcc 2.95, 2.96).
|
||||||
*/
|
*/
|
||||||
pc = first_pc;
|
|
||||||
func_end = pc + 128;
|
func_end = pc + 128;
|
||||||
found_frame_point = 0;
|
found_frame_point = 0;
|
||||||
*frame_offset = 0;
|
info->size = 0;
|
||||||
save_addr = fp + STACK_CORRECTION;
|
save_addr = 0;
|
||||||
while (!done && pc + 2 < func_end)
|
while (!done && pc + 2 < func_end)
|
||||||
{
|
{
|
||||||
struct insn_sequence *seq;
|
struct insn_sequence *seq;
|
||||||
CORE_ADDR val;
|
CORE_ADDR val;
|
||||||
|
|
||||||
seq = m68hc11_analyze_instruction (seq_table, pc, &val);
|
seq = m68hc11_analyze_instruction (seq_table, pc, &val);
|
||||||
if (seq == 0)
|
if (seq == 0)
|
||||||
break;
|
break;
|
||||||
|
@ -764,8 +772,7 @@ m68hc11_guess_from_prologue (CORE_ADDR pc, CORE_ADDR current_pc, CORE_ADDR fp,
|
||||||
break;
|
break;
|
||||||
|
|
||||||
save_addr -= 2;
|
save_addr -= 2;
|
||||||
if (pushed_regs)
|
info->saved_regs[saved_reg].addr = save_addr;
|
||||||
pushed_regs[saved_reg] = save_addr;
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
@ -775,7 +782,7 @@ m68hc11_guess_from_prologue (CORE_ADDR pc, CORE_ADDR current_pc, CORE_ADDR fp,
|
||||||
else if (seq->type == P_SET_FRAME)
|
else if (seq->type == P_SET_FRAME)
|
||||||
{
|
{
|
||||||
found_frame_point = 1;
|
found_frame_point = 1;
|
||||||
*frame_offset = size;
|
info->size = size;
|
||||||
}
|
}
|
||||||
else if (seq->type == P_LOCAL_1)
|
else if (seq->type == P_LOCAL_1)
|
||||||
{
|
{
|
||||||
|
@ -794,7 +801,11 @@ m68hc11_guess_from_prologue (CORE_ADDR pc, CORE_ADDR current_pc, CORE_ADDR fp,
|
||||||
size -= val;
|
size -= val;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
*first_line = pc;
|
if (found_frame_point == 0)
|
||||||
|
info->sp_offset = size;
|
||||||
|
else
|
||||||
|
info->sp_offset = -1;
|
||||||
|
return pc;
|
||||||
}
|
}
|
||||||
|
|
||||||
static CORE_ADDR
|
static CORE_ADDR
|
||||||
|
@ -802,7 +813,7 @@ m68hc11_skip_prologue (CORE_ADDR pc)
|
||||||
{
|
{
|
||||||
CORE_ADDR func_addr, func_end;
|
CORE_ADDR func_addr, func_end;
|
||||||
struct symtab_and_line sal;
|
struct symtab_and_line sal;
|
||||||
int frame_offset;
|
struct m68hc11_unwind_cache tmp_cache = { 0 };
|
||||||
|
|
||||||
/* If we have line debugging information, then the end of the
|
/* If we have line debugging information, then the end of the
|
||||||
prologue should be the first assembly instruction of the
|
prologue should be the first assembly instruction of the
|
||||||
|
@ -814,7 +825,7 @@ m68hc11_skip_prologue (CORE_ADDR pc)
|
||||||
return sal.end;
|
return sal.end;
|
||||||
}
|
}
|
||||||
|
|
||||||
m68hc11_guess_from_prologue (pc, pc, 0, &pc, &frame_offset, 0);
|
pc = m68hc11_scan_prologue (pc, (CORE_ADDR) -1, &tmp_cache);
|
||||||
return pc;
|
return pc;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -846,7 +857,7 @@ m68hc11_frame_chain (struct frame_info *frame)
|
||||||
addr = read_memory_unsigned_integer (addr, 2) & 0x0FFFF;
|
addr = read_memory_unsigned_integer (addr, 2) & 0x0FFFF;
|
||||||
return addr;
|
return addr;
|
||||||
}
|
}
|
||||||
|
#if 0
|
||||||
/* Put here the code to store, into a struct frame_saved_regs, the
|
/* Put here the code to store, into a struct frame_saved_regs, the
|
||||||
addresses of the saved registers of frame described by FRAME_INFO.
|
addresses of the saved registers of frame described by FRAME_INFO.
|
||||||
This includes special registers such as pc and fp saved in special
|
This includes special registers such as pc and fp saved in special
|
||||||
|
@ -928,6 +939,261 @@ m68hc11_init_extra_frame_info (int fromleaf, struct frame_info *fi)
|
||||||
get_frame_extra_info (fi)->return_pc = addr;
|
get_frame_extra_info (fi)->return_pc = addr;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
static CORE_ADDR
|
||||||
|
m68hc11_unwind_pc (struct gdbarch *gdbarch, struct frame_info *next_frame)
|
||||||
|
{
|
||||||
|
ULONGEST pc;
|
||||||
|
|
||||||
|
frame_unwind_unsigned_register (next_frame, gdbarch_pc_regnum (gdbarch),
|
||||||
|
&pc);
|
||||||
|
return pc;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Put here the code to store, into fi->saved_regs, the addresses of
|
||||||
|
the saved registers of frame described by FRAME_INFO. This
|
||||||
|
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. */
|
||||||
|
|
||||||
|
struct m68hc11_unwind_cache *
|
||||||
|
m68hc11_frame_unwind_cache (struct frame_info *next_frame,
|
||||||
|
void **this_prologue_cache)
|
||||||
|
{
|
||||||
|
ULONGEST prev_sp;
|
||||||
|
ULONGEST this_base;
|
||||||
|
struct m68hc11_unwind_cache *info;
|
||||||
|
CORE_ADDR current_pc;
|
||||||
|
int i;
|
||||||
|
|
||||||
|
if ((*this_prologue_cache))
|
||||||
|
return (*this_prologue_cache);
|
||||||
|
|
||||||
|
info = FRAME_OBSTACK_ZALLOC (struct m68hc11_unwind_cache);
|
||||||
|
(*this_prologue_cache) = info;
|
||||||
|
info->saved_regs = trad_frame_alloc_saved_regs (next_frame);
|
||||||
|
|
||||||
|
info->pc = frame_func_unwind (next_frame);
|
||||||
|
|
||||||
|
info->size = 0;
|
||||||
|
info->return_kind = m68hc11_get_return_insn (info->pc);
|
||||||
|
|
||||||
|
/* The SP was moved to the FP. This indicates that a new frame
|
||||||
|
was created. Get THIS frame's FP value by unwinding it from
|
||||||
|
the next frame. */
|
||||||
|
frame_unwind_unsigned_register (next_frame, SOFT_FP_REGNUM, &this_base);
|
||||||
|
if (this_base == 0)
|
||||||
|
{
|
||||||
|
info->base = 0;
|
||||||
|
return info;
|
||||||
|
}
|
||||||
|
|
||||||
|
current_pc = frame_pc_unwind (next_frame);
|
||||||
|
if (info->pc != 0)
|
||||||
|
m68hc11_scan_prologue (info->pc, current_pc, info);
|
||||||
|
|
||||||
|
info->saved_regs[HARD_PC_REGNUM].addr = info->size;
|
||||||
|
|
||||||
|
if (info->sp_offset != (CORE_ADDR) -1)
|
||||||
|
{
|
||||||
|
info->saved_regs[HARD_PC_REGNUM].addr = info->sp_offset;
|
||||||
|
frame_unwind_unsigned_register (next_frame, HARD_SP_REGNUM, &this_base);
|
||||||
|
prev_sp = this_base + info->sp_offset + 2;
|
||||||
|
this_base += STACK_CORRECTION;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
/* The FP points at the last saved register. Adjust the FP back
|
||||||
|
to before the first saved register giving the SP. */
|
||||||
|
prev_sp = this_base + info->size + 2;
|
||||||
|
|
||||||
|
this_base += STACK_CORRECTION;
|
||||||
|
if (soft_regs[SOFT_FP_REGNUM].name)
|
||||||
|
info->saved_regs[SOFT_FP_REGNUM].addr = info->size - 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (info->return_kind == RETURN_RTC)
|
||||||
|
{
|
||||||
|
prev_sp += 1;
|
||||||
|
info->saved_regs[HARD_PAGE_REGNUM].addr = info->size;
|
||||||
|
info->saved_regs[HARD_PC_REGNUM].addr = info->size + 1;
|
||||||
|
}
|
||||||
|
else if (info->return_kind == RETURN_RTI)
|
||||||
|
{
|
||||||
|
prev_sp += 7;
|
||||||
|
info->saved_regs[HARD_CCR_REGNUM].addr = info->size;
|
||||||
|
info->saved_regs[HARD_D_REGNUM].addr = info->size + 1;
|
||||||
|
info->saved_regs[HARD_X_REGNUM].addr = info->size + 3;
|
||||||
|
info->saved_regs[HARD_Y_REGNUM].addr = info->size + 5;
|
||||||
|
info->saved_regs[HARD_PC_REGNUM].addr = info->size + 7;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Add 1 here to adjust for the post-decrement nature of the push
|
||||||
|
instruction.*/
|
||||||
|
info->prev_sp = prev_sp;
|
||||||
|
|
||||||
|
info->base = this_base;
|
||||||
|
|
||||||
|
/* Adjust all the saved registers so that they contain addresses and not
|
||||||
|
offsets. */
|
||||||
|
for (i = 0; i < NUM_REGS + NUM_PSEUDO_REGS - 1; i++)
|
||||||
|
if (trad_frame_addr_p (info->saved_regs, i))
|
||||||
|
{
|
||||||
|
info->saved_regs[i].addr += this_base;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* The previous frame's SP needed to be computed. Save the computed
|
||||||
|
value. */
|
||||||
|
trad_frame_set_value (info->saved_regs, HARD_SP_REGNUM, info->prev_sp);
|
||||||
|
|
||||||
|
return info;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Given a GDB frame, determine the address of the calling function's
|
||||||
|
frame. This will be used to create a new GDB frame struct. */
|
||||||
|
|
||||||
|
static void
|
||||||
|
m68hc11_frame_this_id (struct frame_info *next_frame,
|
||||||
|
void **this_prologue_cache,
|
||||||
|
struct frame_id *this_id)
|
||||||
|
{
|
||||||
|
struct m68hc11_unwind_cache *info
|
||||||
|
= m68hc11_frame_unwind_cache (next_frame, this_prologue_cache);
|
||||||
|
CORE_ADDR base;
|
||||||
|
CORE_ADDR func;
|
||||||
|
struct frame_id id;
|
||||||
|
|
||||||
|
/* The FUNC is easy. */
|
||||||
|
func = frame_func_unwind (next_frame);
|
||||||
|
|
||||||
|
/* This is meant to halt the backtrace at "_start". Make sure we
|
||||||
|
don't halt it at a generic dummy frame. */
|
||||||
|
if (inside_entry_file (func))
|
||||||
|
return;
|
||||||
|
|
||||||
|
/* Hopefully the prologue analysis either correctly determined the
|
||||||
|
frame's base (which is the SP from the previous frame), or set
|
||||||
|
that base to "NULL". */
|
||||||
|
base = info->prev_sp;
|
||||||
|
if (base == 0)
|
||||||
|
return;
|
||||||
|
|
||||||
|
id = frame_id_build (base, func);
|
||||||
|
#if 0
|
||||||
|
/* Check that we're not going round in circles with the same frame
|
||||||
|
ID (but avoid applying the test to sentinel frames which do go
|
||||||
|
round in circles). Can't use frame_id_eq() as that doesn't yet
|
||||||
|
compare the frame's PC value. */
|
||||||
|
if (frame_relative_level (next_frame) >= 0
|
||||||
|
&& get_frame_type (next_frame) != DUMMY_FRAME
|
||||||
|
&& frame_id_eq (get_frame_id (next_frame), id))
|
||||||
|
return;
|
||||||
|
#endif
|
||||||
|
(*this_id) = id;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
m68hc11_frame_prev_register (struct frame_info *next_frame,
|
||||||
|
void **this_prologue_cache,
|
||||||
|
int regnum, int *optimizedp,
|
||||||
|
enum lval_type *lvalp, CORE_ADDR *addrp,
|
||||||
|
int *realnump, void *bufferp)
|
||||||
|
{
|
||||||
|
struct m68hc11_unwind_cache *info
|
||||||
|
= m68hc11_frame_unwind_cache (next_frame, this_prologue_cache);
|
||||||
|
|
||||||
|
trad_frame_prev_register (next_frame, info->saved_regs, regnum,
|
||||||
|
optimizedp, lvalp, addrp, realnump, bufferp);
|
||||||
|
|
||||||
|
if (regnum == HARD_PC_REGNUM)
|
||||||
|
{
|
||||||
|
/* Take into account the 68HC12 specific call (PC + page). */
|
||||||
|
if (info->return_kind == RETURN_RTC
|
||||||
|
&& *addrp >= 0x08000 && *addrp < 0x0c000
|
||||||
|
&& USE_PAGE_REGISTER)
|
||||||
|
{
|
||||||
|
int page_optimized;
|
||||||
|
|
||||||
|
CORE_ADDR page;
|
||||||
|
|
||||||
|
trad_frame_prev_register (next_frame, info->saved_regs,
|
||||||
|
HARD_PAGE_REGNUM, &page_optimized,
|
||||||
|
0, &page, 0, 0);
|
||||||
|
*addrp -= 0x08000;
|
||||||
|
*addrp += ((page & 0x0ff) << 14);
|
||||||
|
*addrp += 0x1000000;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static const struct frame_unwind m68hc11_frame_unwind = {
|
||||||
|
NORMAL_FRAME,
|
||||||
|
m68hc11_frame_this_id,
|
||||||
|
m68hc11_frame_prev_register
|
||||||
|
};
|
||||||
|
|
||||||
|
const struct frame_unwind *
|
||||||
|
m68hc11_frame_p (CORE_ADDR pc)
|
||||||
|
{
|
||||||
|
return &m68hc11_frame_unwind;
|
||||||
|
}
|
||||||
|
|
||||||
|
static CORE_ADDR
|
||||||
|
m68hc11_frame_base_address (struct frame_info *next_frame, void **this_cache)
|
||||||
|
{
|
||||||
|
struct m68hc11_unwind_cache *info
|
||||||
|
= m68hc11_frame_unwind_cache (next_frame, this_cache);
|
||||||
|
|
||||||
|
return info->base;
|
||||||
|
}
|
||||||
|
|
||||||
|
static CORE_ADDR
|
||||||
|
m68hc11_frame_args_address (struct frame_info *next_frame, void **this_cache)
|
||||||
|
{
|
||||||
|
CORE_ADDR addr;
|
||||||
|
struct m68hc11_unwind_cache *info
|
||||||
|
= m68hc11_frame_unwind_cache (next_frame, this_cache);
|
||||||
|
|
||||||
|
addr = info->base + info->size;
|
||||||
|
if (info->return_kind == RETURN_RTC)
|
||||||
|
addr += 1;
|
||||||
|
else if (info->return_kind == RETURN_RTI)
|
||||||
|
addr += 7;
|
||||||
|
|
||||||
|
return addr;
|
||||||
|
}
|
||||||
|
|
||||||
|
static const struct frame_base m68hc11_frame_base = {
|
||||||
|
&m68hc11_frame_unwind,
|
||||||
|
m68hc11_frame_base_address,
|
||||||
|
m68hc11_frame_base_address,
|
||||||
|
m68hc11_frame_args_address
|
||||||
|
};
|
||||||
|
|
||||||
|
static CORE_ADDR
|
||||||
|
m68hc11_unwind_sp (struct gdbarch *gdbarch, struct frame_info *next_frame)
|
||||||
|
{
|
||||||
|
ULONGEST sp;
|
||||||
|
frame_unwind_unsigned_register (next_frame, HARD_SP_REGNUM, &sp);
|
||||||
|
return sp;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Assuming NEXT_FRAME->prev is a dummy, return the frame ID of that
|
||||||
|
dummy frame. The frame ID's base needs to match the TOS value
|
||||||
|
saved by save_dummy_frame_tos(), and the PC match the dummy frame's
|
||||||
|
breakpoint. */
|
||||||
|
|
||||||
|
static struct frame_id
|
||||||
|
m68hc11_unwind_dummy_id (struct gdbarch *gdbarch, struct frame_info *next_frame)
|
||||||
|
{
|
||||||
|
ULONGEST tos;
|
||||||
|
CORE_ADDR pc = frame_pc_unwind (next_frame);
|
||||||
|
|
||||||
|
frame_unwind_unsigned_register (next_frame, SOFT_FP_REGNUM, &tos);
|
||||||
|
tos += 2;
|
||||||
|
return frame_id_build (tos, pc);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/* Get and print the register from the given frame. */
|
/* Get and print the register from the given frame. */
|
||||||
|
@ -1410,10 +1676,6 @@ m68hc11_gdbarch_init (struct gdbarch_info info,
|
||||||
gdbarch = gdbarch_alloc (&info, tdep);
|
gdbarch = gdbarch_alloc (&info, tdep);
|
||||||
tdep->elf_flags = elf_flags;
|
tdep->elf_flags = elf_flags;
|
||||||
|
|
||||||
/* NOTE: cagney/2002-12-06: This can be deleted when this arch is
|
|
||||||
ready to unwind the PC first (see frame.c:get_prev_frame()). */
|
|
||||||
set_gdbarch_deprecated_init_frame_pc (gdbarch, init_frame_pc_default);
|
|
||||||
|
|
||||||
switch (info.bfd_arch_info->arch)
|
switch (info.bfd_arch_info->arch)
|
||||||
{
|
{
|
||||||
case bfd_arch_m68hc11:
|
case bfd_arch_m68hc11:
|
||||||
|
@ -1461,16 +1723,16 @@ m68hc11_gdbarch_init (struct gdbarch_info info,
|
||||||
/* Characters are unsigned. */
|
/* Characters are unsigned. */
|
||||||
set_gdbarch_char_signed (gdbarch, 0);
|
set_gdbarch_char_signed (gdbarch, 0);
|
||||||
|
|
||||||
|
set_gdbarch_unwind_pc (gdbarch, m68hc11_unwind_pc);
|
||||||
|
set_gdbarch_unwind_sp (gdbarch, m68hc11_unwind_sp);
|
||||||
|
|
||||||
/* Set register info. */
|
/* Set register info. */
|
||||||
set_gdbarch_fp0_regnum (gdbarch, -1);
|
set_gdbarch_fp0_regnum (gdbarch, -1);
|
||||||
set_gdbarch_deprecated_frame_init_saved_regs (gdbarch, m68hc11_frame_init_saved_regs);
|
|
||||||
set_gdbarch_frame_args_skip (gdbarch, 0);
|
set_gdbarch_frame_args_skip (gdbarch, 0);
|
||||||
|
|
||||||
set_gdbarch_write_pc (gdbarch, generic_target_write_pc);
|
set_gdbarch_write_pc (gdbarch, generic_target_write_pc);
|
||||||
set_gdbarch_deprecated_dummy_write_sp (gdbarch, deprecated_write_sp);
|
|
||||||
|
|
||||||
set_gdbarch_sp_regnum (gdbarch, HARD_SP_REGNUM);
|
set_gdbarch_sp_regnum (gdbarch, HARD_SP_REGNUM);
|
||||||
set_gdbarch_deprecated_fp_regnum (gdbarch, SOFT_FP_REGNUM);
|
|
||||||
set_gdbarch_register_name (gdbarch, m68hc11_register_name);
|
set_gdbarch_register_name (gdbarch, m68hc11_register_name);
|
||||||
set_gdbarch_register_type (gdbarch, m68hc11_register_type);
|
set_gdbarch_register_type (gdbarch, m68hc11_register_type);
|
||||||
set_gdbarch_pseudo_register_read (gdbarch, m68hc11_pseudo_register_read);
|
set_gdbarch_pseudo_register_read (gdbarch, m68hc11_pseudo_register_read);
|
||||||
|
@ -1478,27 +1740,15 @@ m68hc11_gdbarch_init (struct gdbarch_info info,
|
||||||
|
|
||||||
set_gdbarch_push_dummy_call (gdbarch, m68hc11_push_dummy_call);
|
set_gdbarch_push_dummy_call (gdbarch, m68hc11_push_dummy_call);
|
||||||
|
|
||||||
set_gdbarch_deprecated_get_saved_register (gdbarch, deprecated_generic_get_saved_register);
|
|
||||||
set_gdbarch_extract_return_value (gdbarch, m68hc11_extract_return_value);
|
set_gdbarch_extract_return_value (gdbarch, m68hc11_extract_return_value);
|
||||||
set_gdbarch_return_value_on_stack (gdbarch, m68hc11_return_value_on_stack);
|
set_gdbarch_return_value_on_stack (gdbarch, m68hc11_return_value_on_stack);
|
||||||
|
|
||||||
set_gdbarch_deprecated_store_struct_return (gdbarch, m68hc11_store_struct_return);
|
|
||||||
set_gdbarch_store_return_value (gdbarch, m68hc11_store_return_value);
|
set_gdbarch_store_return_value (gdbarch, m68hc11_store_return_value);
|
||||||
set_gdbarch_extract_struct_value_address (gdbarch, m68hc11_extract_struct_value_address);
|
set_gdbarch_extract_struct_value_address (gdbarch, m68hc11_extract_struct_value_address);
|
||||||
|
|
||||||
set_gdbarch_deprecated_frame_chain (gdbarch, m68hc11_frame_chain);
|
|
||||||
set_gdbarch_deprecated_frame_saved_pc (gdbarch, m68hc11_frame_saved_pc);
|
|
||||||
set_gdbarch_deprecated_frame_args_address (gdbarch, m68hc11_frame_args_address);
|
|
||||||
set_gdbarch_deprecated_saved_pc_after_call (gdbarch, m68hc11_saved_pc_after_call);
|
|
||||||
|
|
||||||
set_gdbarch_deprecated_get_saved_register (gdbarch, deprecated_generic_get_saved_register);
|
|
||||||
|
|
||||||
set_gdbarch_deprecated_store_struct_return (gdbarch, m68hc11_store_struct_return);
|
|
||||||
set_gdbarch_store_return_value (gdbarch, m68hc11_store_return_value);
|
set_gdbarch_store_return_value (gdbarch, m68hc11_store_return_value);
|
||||||
set_gdbarch_extract_struct_value_address (gdbarch, m68hc11_extract_struct_value_address);
|
set_gdbarch_extract_struct_value_address (gdbarch, m68hc11_extract_struct_value_address);
|
||||||
set_gdbarch_use_struct_convention (gdbarch, m68hc11_use_struct_convention);
|
set_gdbarch_use_struct_convention (gdbarch, m68hc11_use_struct_convention);
|
||||||
set_gdbarch_deprecated_init_extra_frame_info (gdbarch, m68hc11_init_extra_frame_info);
|
|
||||||
set_gdbarch_deprecated_pop_frame (gdbarch, m68hc11_pop_frame);
|
|
||||||
set_gdbarch_skip_prologue (gdbarch, m68hc11_skip_prologue);
|
set_gdbarch_skip_prologue (gdbarch, m68hc11_skip_prologue);
|
||||||
set_gdbarch_inner_than (gdbarch, core_addr_lessthan);
|
set_gdbarch_inner_than (gdbarch, core_addr_lessthan);
|
||||||
set_gdbarch_decr_pc_after_break (gdbarch, 0);
|
set_gdbarch_decr_pc_after_break (gdbarch, 0);
|
||||||
|
@ -1511,6 +1761,21 @@ m68hc11_gdbarch_init (struct gdbarch_info info,
|
||||||
set_gdbarch_register_reggroup_p (gdbarch, m68hc11_register_reggroup_p);
|
set_gdbarch_register_reggroup_p (gdbarch, m68hc11_register_reggroup_p);
|
||||||
set_gdbarch_print_registers_info (gdbarch, m68hc11_print_registers_info);
|
set_gdbarch_print_registers_info (gdbarch, m68hc11_print_registers_info);
|
||||||
|
|
||||||
|
/* Hook in the DWARF CFI frame unwinder. */
|
||||||
|
frame_unwind_append_sniffer (gdbarch, dwarf2_frame_sniffer);
|
||||||
|
set_gdbarch_dwarf2_build_frame_info (gdbarch, dwarf2_build_frame_info);
|
||||||
|
|
||||||
|
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. */
|
||||||
|
set_gdbarch_unwind_dummy_id (gdbarch, m68hc11_unwind_dummy_id);
|
||||||
|
|
||||||
|
/* Return the unwound PC value. */
|
||||||
|
set_gdbarch_unwind_pc (gdbarch, m68hc11_unwind_pc);
|
||||||
|
|
||||||
/* Minsymbol frobbing. */
|
/* Minsymbol frobbing. */
|
||||||
set_gdbarch_elf_make_msymbol_special (gdbarch,
|
set_gdbarch_elf_make_msymbol_special (gdbarch,
|
||||||
m68hc11_elf_make_msymbol_special);
|
m68hc11_elf_make_msymbol_special);
|
||||||
|
|
Loading…
Reference in New Issue