This is the mail archive of the
gdb-patches@sources.redhat.com
mailing list for the GDB project.
[PATCH] new frame code for h8300 target
- From: Yoshinori Sato <ysato at users dot sourceforge dot jp>
- To: gdb-patches at sources dot redhat dot com
- Date: Mon, 15 Nov 2004 01:23:21 +0900
- Subject: [PATCH] new frame code for h8300 target
It is a new frame code patch for a gdb-6.3 h8300 target.
Because I still use it, I am at a loss very that it is deleted.
===File ~/gdb-6.3/gdb/h8300-tdep.c.diff=====================
--- h8300-tdep.c~ 2004-08-03 04:44:40.000000000 +0900
+++ h8300-tdep.c 2004-11-15 01:03:08.000000000 +0900
@@ -36,6 +36,10 @@
#include "gdbcmd.h"
#include "gdb_assert.h"
#include "dis-asm.h"
+#include "dwarf2-frame.h"
+#include "frame.h"
+#include "frame-base.h"
+#include "frame-unwind.h"
/* Extra info which is saved in each frame_info. */
struct frame_extra_info
@@ -81,6 +85,8 @@
E_VBR_REGNUM
};
+#define H8300_MAX_NUM_REGS 18
+
#define E_PSEUDO_CCR_REGNUM (NUM_REGS)
#define E_PSEUDO_EXR_REGNUM (NUM_REGS+1)
@@ -286,281 +292,409 @@
return start_pc;
}
-/* Fetch the instruction at ADDR, returning 0 if ADDR is beyond LIM or
- is not the address of a valid instruction, the address of the next
- instruction beyond ADDR otherwise. *PWORD1 receives the first word
- of the instruction. */
-
static CORE_ADDR
-h8300_next_prologue_insn (CORE_ADDR addr,
- CORE_ADDR lim,
- unsigned short* pword1)
+h8300_unwind_pc (struct gdbarch *gdbarch, struct frame_info *next_frame)
{
- char buf[2];
- if (addr < lim + 8)
- {
- read_memory (addr, buf, 2);
- *pword1 = extract_signed_integer (buf, 2);
+ char buf[8];
- return addr + 2;
- }
- return 0;
+ frame_unwind_register (next_frame, E_PC_REGNUM, buf);
+ return extract_typed_address (buf, builtin_type_void_func_ptr);
}
-/* Examine the prologue of a function. `ip' points to the first instruction.
- `limit' is the limit of the prologue (e.g. the addr of the first
- linenumber, or perhaps the program counter if we're stepping through).
- `frame_sp' is the stack pointer value in use in this frame.
- `fsr' is a pointer to a frame_saved_regs structure into which we put
- info about the registers saved by this frame.
- `fi' is a struct frame_info pointer; we fill in various fields in it
- to reflect the offsets of the arg pointer and the locals pointer. */
-
-/* Any function with a frame looks like this
- SECOND ARG
- FIRST ARG
- RET PC
- SAVED R2
- SAVED R3
- SAVED FP <-FP POINTS HERE
- LOCALS0
- LOCALS1 <-SP POINTS HERE
- */
+static struct frame_id
+h8300_unwind_dummy_id (struct gdbarch *gdbarch, struct frame_info *next_frame)
+{
+ char buf[4];
+ CORE_ADDR fp;
-static CORE_ADDR
-h8300_examine_prologue (CORE_ADDR ip, CORE_ADDR limit,
- CORE_ADDR after_prolog_fp, CORE_ADDR *fsr,
- struct frame_info *fi)
-{
- CORE_ADDR next_ip;
- int r;
- int have_fp = 0;
- unsigned short insn_word;
- /* Number of things pushed onto stack, starts at 2/4, 'cause the
- PC is already there */
- unsigned int reg_save_depth = BINWORD;
+ frame_unwind_register (next_frame, E_FP_REGNUM, buf);
+ fp = extract_unsigned_integer (buf, 4);
- unsigned int auto_depth = 0; /* Number of bytes of autos */
+ return frame_id_build (fp, frame_pc_unwind (next_frame));
+}
- char in_frame[11]; /* One for each reg */
+struct h8300_frame_cache
+{
+ /* Base address. */
+ CORE_ADDR base;
+ CORE_ADDR sp_offset;
+ CORE_ADDR pc;
- int adjust = 0;
+ /* Saved registers. */
+ CORE_ADDR saved_regs[H8300_MAX_NUM_REGS];
+ CORE_ADDR saved_sp;
- memset (in_frame, 1, 11);
- for (r = 0; r < 8; r++)
- {
- fsr[r] = 0;
- }
- if (after_prolog_fp == 0)
- {
- after_prolog_fp = read_register (E_SP_REGNUM);
- }
+ /* Stack space reserved for local variables. */
+ long locals;
+};
- /* If the PC isn't valid, quit now. */
- if (ip == 0 || ip & (is_h8300hmode (current_gdbarch) &&
- !is_h8300_normal_mode (current_gdbarch) ? ~0xffffff : ~0xffff))
- return 0;
+/* Normal frames. */
- next_ip = h8300_next_prologue_insn (ip, limit, &insn_word);
+/* Allocate and initialize a frame cache. */
- if (insn_word == 0x0100) /* mov.l */
- {
- insn_word = read_memory_unsigned_integer (ip + 2, 2);
- adjust = 2;
- }
+static struct h8300_frame_cache *
+h8300_alloc_frame_cache (void)
+{
+ struct h8300_frame_cache *cache;
+ int i;
- /* Skip over any fp push instructions */
- fsr[E_FP_REGNUM] = after_prolog_fp;
- while (next_ip && IS_PUSH_FP (insn_word))
- {
- ip = next_ip + adjust;
+ cache = FRAME_OBSTACK_ZALLOC (struct h8300_frame_cache);
- in_frame[insn_word & 0x7] = reg_save_depth;
- next_ip = h8300_next_prologue_insn (ip, limit, &insn_word);
- reg_save_depth += 2 + adjust;
- }
+ /* Base address. */
+ cache->base = 0;
+ cache->sp_offset = -4;
+ cache->pc = 0;
- /* Is this a move into the fp */
- if (next_ip && IS_MOV_SP_FP (insn_word))
- {
- ip = next_ip;
- next_ip = h8300_next_prologue_insn (ip, limit, &insn_word);
- have_fp = 1;
- }
+ /* Saved registers. We initialize these to -1 since zero is a valid
+ offset (that's where %fp is supposed to be stored). */
+ for (i = 0; i < NUM_REGS; i++)
+ cache->saved_regs[i] = -1;
- /* Skip over any stack adjustment, happens either with a number of
- sub#2,sp or a mov #x,r5 sub r5,sp */
+ /* Frameless until proven otherwise. */
+ cache->locals = -1;
- if (next_ip && (IS_SUB2_SP (insn_word) || IS_SUB4_SP (insn_word)))
- {
- while (next_ip && (IS_SUB2_SP (insn_word) || IS_SUB4_SP (insn_word)))
- {
- auto_depth += IS_SUB2_SP (insn_word) ? 2 : 4;
- ip = next_ip;
- next_ip = h8300_next_prologue_insn (ip, limit, &insn_word);
- }
- }
- else
+ return cache;
+}
+
+/* Check whether PC points at a code that sets up a new stack frame.
+ If so, it updates CACHE and returns the address of the first
+ instruction after the sequence that sets removes the "hidden"
+ argument from the stack or CURRENT_PC, whichever is smaller.
+ Otherwise, return PC. */
+
+static CORE_ADDR
+h8300_analyze_frame_setup (CORE_ADDR pc, CORE_ADDR current_pc,
+ struct h8300_frame_cache *cache)
+{
+ unsigned int op;
+ int subs_count;
+
+ if (pc >= current_pc)
+ return current_pc;
+
+ op = read_memory_unsigned_integer (pc, 4);
+
+ if (op == 0x6df60d76)
{
- if (next_ip && IS_MOVK_R5 (insn_word))
+ /* mov.w r6,@-sp; mov.w sp,r6 */
+ cache->saved_regs[E_FP_REGNUM] = 0;
+ cache->sp_offset += 2;
+ op = read_memory_unsigned_integer (pc + 4, 4);
+ if (((op >> 16) & 0xfff0) == 0x7900)
{
- ip = next_ip;
- next_ip = h8300_next_prologue_insn (ip, limit, &insn_word);
- auto_depth += insn_word;
-
- next_ip = h8300_next_prologue_insn (next_ip, limit, &insn_word);
- auto_depth += insn_word;
+ /* mov.w #imm,rN */
+ cache->locals = -(short)(op & 0xffff);
+ return pc + 8;
}
- if (next_ip && IS_SUBL_SP (insn_word))
+ else if((op >> 16) == 0x1b87)
{
- ip = next_ip;
- auto_depth += read_memory_unsigned_integer (ip, 4);
- ip += 4;
-
- next_ip = h8300_next_prologue_insn (ip, limit, &insn_word);
+ /* subs #2,sp */
+ for (cache->locals = 0, pc += 4;
+ read_memory_unsigned_integer (pc, 2) == 0x1b87;
+ pc += 2, cache->locals += 2);
+ return pc;
}
}
-
- /* Now examine the push insns to determine where everything lives
- on the stack. */
- while (1)
+ else if (op == 0x01006df6)
{
- adjust = 0;
- if (!next_ip)
- break;
-
- if (insn_word == 0x0100)
+ /* mov.l er6,@-sp */
+ op = read_memory_unsigned_integer (pc+4, 2);
+ if (op == 0x0ff6)
{
- ip = next_ip;
- next_ip = h8300_next_prologue_insn (ip, limit, &insn_word);
- adjust = 2;
+ /* mov.l sp,er6 */
+ op = read_memory_unsigned_integer (pc+6, 2);
+ if (op == 0x7a17)
+ {
+ /* add.l #-n,sp */
+ cache->locals = -read_memory_unsigned_integer (pc+8, 4);
+ return pc + 12;
+ }
+ else if (op == 0x1b97)
+ {
+ /* subs #4,sp */
+ for (cache->locals = 0, pc += 6;
+ read_memory_unsigned_integer (pc, 2) == 0x1b97;
+ pc += 2, cache->locals += 2);
+ return pc;
+ }
}
+ }
- if (IS_PUSH (insn_word))
- {
- auto_depth += 2 + adjust;
- fsr[insn_word & 0x7] = after_prolog_fp - auto_depth;
- ip = next_ip;
- next_ip = h8300_next_prologue_insn (ip, limit, &insn_word);
- continue;
- }
+ return pc;
+}
- /* Now check for push multiple insns. */
- if (insn_word == 0x0110 || insn_word == 0x0120 || insn_word == 0x0130)
- {
- int count = ((insn_word >> 4) & 0xf) + 1;
- int start, i;
+/* Check whether PC points at code that saves registers on the stack.
+ If so, it updates CACHE and returns the address of the first
+ instruction after the register saves or CURRENT_PC, whichever is
+ smaller. Otherwise, return PC. */
- ip = next_ip;
- next_ip = h8300_next_prologue_insn (ip, limit, &insn_word);
- start = insn_word & 0x7;
+static CORE_ADDR
+h8300_analyze_register_saves (CORE_ADDR pc, CORE_ADDR current_pc,
+ struct h8300_frame_cache *cache)
+{
+ if (cache->locals >= 0)
+ {
+ CORE_ADDR offset;
+ int op;
+ int i, regno;
- for (i = start; i < start + count; i++)
+ offset = - cache->locals;
+ while (pc < current_pc)
+ {
+ op = read_memory_unsigned_integer (pc, 2);
+ if ((op & 0xfff0) == 0x6df0)
+ {
+ /* mov.w rN,@-sp*/
+ regno = op & 0x000f;
+ cache->saved_regs[regno] = offset;
+ offset -= 2;
+ pc += 2;
+ }
+ else if (op == 0x0100)
+ {
+ op = read_memory_unsigned_integer (pc+2, 2);
+ if ((op & 0xfff0) == 0x6df0)
+ {
+ /* mov.l erN,@-sp*/
+ regno = op & 0x000f;
+ cache->saved_regs[regno] = offset;
+ offset -= 4;
+ pc += 4;
+ }
+ else
+ break ;
+ }
+ else if ((op & 0xffcf) == 0x0100)
{
- auto_depth += 4;
- fsr[i] = after_prolog_fp - auto_depth;
+ int op1;
+ op1 = read_memory_unsigned_integer (pc+2, 2);
+ if ((op1 & 0xfff0) == 0x6df0)
+ {
+ /* stm.l reglist,@-sp*/
+ i = ((op & 0x0030) >> 4) + 1;
+ regno = op1 & 0x000f;
+ for (; i > 0; regno++, --i) {
+ cache->saved_regs[regno] = offset;
+ offset -= 4;
+ }
+ pc += 4;
+ }
+ else
+ break ;
}
+ else
+ break;
}
- break;
}
+ return pc;
+}
- /* The PC is at a known place */
- get_frame_extra_info (fi)->from_pc =
- read_memory_unsigned_integer (after_prolog_fp + BINWORD, BINWORD);
-
- /* Rememeber any others too */
- in_frame[E_PC_REGNUM] = 0;
-
- if (have_fp)
- /* We keep the old FP in the SP spot */
- fsr[E_SP_REGNUM] = read_memory_unsigned_integer (fsr[E_FP_REGNUM],
- BINWORD);
- else
- fsr[E_SP_REGNUM] = after_prolog_fp + auto_depth;
- return (ip);
+/* Do a full analysis of the prologue at PC and update CACHE
+ accordingly. Bail out early if CURRENT_PC is reached. Return the
+ address where the analysis stopped.
+
+ We handle all cases that can be generated by gcc.
+
+ For allocating a stack frame:
+
+ mov.w r6,@-sp
+ mov.w sp,r6
+ mov.w #-n,rN
+ add.w rN,sp
+
+ mov.w r6,@-sp
+ mov.w sp,r6
+ subs #2,sp
+ (repeat)
+
+ mov.l er6,@-sp
+ mov.l sp,er6
+ add.l #-n,sp
+
+ mov.w r6,@-sp
+ mov.w sp,r6
+ subs #4,sp
+ (repeat)
+
+ For saving registers:
+
+ mov.w rN,@-sp
+ mov.l erN,@-sp
+ stm.l reglist,@-sp
+
+ For setting up the PIC register:
+
+ Future equivalence...
+
+ */
+
+static CORE_ADDR
+h8300_analyze_prologue (CORE_ADDR pc, CORE_ADDR current_pc,
+ struct h8300_frame_cache *cache)
+{
+ unsigned int op;
+
+ pc = h8300_analyze_frame_setup (pc, current_pc, cache);
+ pc = h8300_analyze_register_saves (pc, current_pc, cache);
+ if (pc >= current_pc)
+ return current_pc;
+
+ /* PIC support */
+
+ return pc;
}
-static void
-h8300_frame_init_saved_regs (struct frame_info *fi)
+static struct h8300_frame_cache *
+h8300_frame_cache (struct frame_info *next_frame, void **this_cache)
{
- CORE_ADDR func_addr, func_end;
+ struct h8300_frame_cache *cache;
+ char buf[4];
+ int i;
+
+ if (*this_cache)
+ return *this_cache;
+
+ cache = h8300_alloc_frame_cache ();
+ *this_cache = cache;
+
+ /* In principle, for normal frames, %fp holds the frame pointer,
+ which holds the base address for the current stack frame.
+ However, for functions that don't need it, the frame pointer is
+ optional. For these "frameless" functions the frame pointer is
+ actually the frame pointer of the calling frame. Signal
+ trampolines are just a special case of a "frameless" function.
+ They (usually) share their frame pointer with the frame that was
+ in progress when the signal occurred. */
- if (!deprecated_get_frame_saved_regs (fi))
+ frame_unwind_register (next_frame, E_FP_REGNUM, buf);
+ cache->base = extract_unsigned_integer (buf, 4);
+ if (cache->base == 0)
+ return cache;
+
+ /* For normal frames, %pc is stored at 4(%fp). */
+ cache->saved_regs[E_PC_REGNUM] = 4;
+
+ cache->pc = frame_func_unwind (next_frame);
+ if (cache->pc != 0)
+ h8300_analyze_prologue (cache->pc, frame_pc_unwind (next_frame), cache);
+
+ if (cache->locals < 0)
{
- frame_saved_regs_zalloc (fi);
+ /* We didn't find a valid frame, which means that CACHE->base
+ currently holds the frame pointer for our calling frame. If
+ we're at the start of a function, or somewhere half-way its
+ prologue, the function's frame probably hasn't been fully
+ setup yet. Try to reconstruct the base address for the stack
+ frame by looking at the stack pointer. For truly "frameless"
+ functions this might work too. */
- /* Find the beginning of this function, so we can analyze its
- prologue. */
- if (find_pc_partial_function (get_frame_pc (fi), NULL,
- &func_addr, &func_end))
- {
- struct symtab_and_line sal = find_pc_line (func_addr, 0);
- CORE_ADDR limit = (sal.end && sal.end < get_frame_pc (fi))
- ? sal.end : get_frame_pc (fi);
- /* This will fill in fields in fi. */
- h8300_examine_prologue (func_addr, limit, get_frame_base (fi),
- deprecated_get_frame_saved_regs (fi), fi);
- }
- /* Else we're out of luck (can't debug completely stripped code).
- FIXME. */
+ frame_unwind_register (next_frame, E_SP_REGNUM, buf);
+ cache->base = extract_unsigned_integer (buf, 4) + cache->sp_offset;
}
-}
-/* Given a GDB frame, determine the address of the calling function's
- frame. This will be used to create a new GDB frame struct, and
- then DEPRECATED_INIT_EXTRA_FRAME_INFO and DEPRECATED_INIT_FRAME_PC
- will be called for the new frame.
+ /* Now that we have the base address for the stack frame we can
+ calculate the value of %sp in the calling frame. */
+ cache->saved_sp = cache->base;
- For us, the frame address is its stack pointer value, so we look up
- the function prologue to determine the caller's sp value, and
- return it. */
+ /* Adjust all the saved registers such that they contain addresses
+ instead of offsets. */
+ for (i = 0; i < NUM_REGS; i++)
+ if (cache->saved_regs[i] != -1)
+ cache->saved_regs[i] += cache->base;
-static CORE_ADDR
-h8300_frame_chain (struct frame_info *thisframe)
+ return cache;
+}
+
+static void
+h8300_frame_this_id (struct frame_info *next_frame, void **this_cache,
+ struct frame_id *this_id)
{
- if (deprecated_pc_in_call_dummy (get_frame_pc (thisframe)))
- { /* initialize the from_pc now */
- get_frame_extra_info (thisframe)->from_pc =
- deprecated_read_register_dummy (get_frame_pc (thisframe),
- get_frame_base (thisframe),
- E_PC_REGNUM);
- return get_frame_base (thisframe);
- }
- return deprecated_get_frame_saved_regs (thisframe)[E_SP_REGNUM];
+ struct h8300_frame_cache *cache = h8300_frame_cache (next_frame, this_cache);
+
+ /* This marks the outermost frame. */
+ if (cache->base == 0)
+ return;
+
+ /* See the end of m68k_push_dummy_call. */
+ *this_id = frame_id_build (cache->base , cache->pc);
}
-/* Return the saved PC from this frame.
+static void
+h8300_frame_prev_register (struct frame_info *next_frame, void **this_cache,
+ int regnum, int *optimizedp,
+ enum lval_type *lvalp, CORE_ADDR *addrp,
+ int *realnump, void *valuep)
+{
+ struct h8300_frame_cache *cache = h8300_frame_cache (next_frame, this_cache);
+
+ gdb_assert (regnum >= 0);
+
+ if (regnum == E_SP_REGNUM && cache->saved_sp)
+ {
+ *optimizedp = 0;
+ *lvalp = not_lval;
+ *addrp = 0;
+ *realnump = -1;
+ if (valuep)
+ {
+ /* Store the value. */
+ store_unsigned_integer (valuep, 4, cache->saved_sp);
+ }
+ return;
+ }
+
+ if (regnum < NUM_REGS && cache->saved_regs[regnum] != -1)
+ {
+ *optimizedp = 0;
+ *lvalp = lval_memory;
+ *addrp = cache->saved_regs[regnum];
+ *realnump = -1;
+ if (valuep)
+ {
+ /* Read the value in from memory. */
+ read_memory (*addrp, valuep,
+ register_size (current_gdbarch, regnum));
+ }
+ return;
+ }
- If the frame has a memory copy of SRP_REGNUM, use that. If not,
- just use the register SRP_REGNUM itself. */
+ frame_register_unwind (next_frame, regnum,
+ optimizedp, lvalp, addrp, realnump, valuep);
+}
-static CORE_ADDR
-h8300_frame_saved_pc (struct frame_info *frame)
+static const struct frame_unwind h8300_frame_unwind =
{
- if (deprecated_pc_in_call_dummy (get_frame_pc (frame)))
- return deprecated_read_register_dummy (get_frame_pc (frame),
- get_frame_base (frame),
- E_PC_REGNUM);
- else
- return get_frame_extra_info (frame)->from_pc;
+ NORMAL_FRAME,
+ h8300_frame_this_id,
+ h8300_frame_prev_register
+};
+
+static const struct frame_unwind *
+h8300_frame_sniffer (struct frame_info *next_frame)
+{
+ return &h8300_frame_unwind;
}
-static void
-h8300_init_extra_frame_info (int fromleaf, struct frame_info *fi)
+/* Fetch the instruction at ADDR, returning 0 if ADDR is beyond LIM or
+ is not the address of a valid instruction, the address of the next
+ instruction beyond ADDR otherwise. *PWORD1 receives the first word
+ of the instruction. */
+
+static CORE_ADDR
+h8300_next_prologue_insn (CORE_ADDR addr,
+ CORE_ADDR lim,
+ unsigned short* pword1)
{
- if (!get_frame_extra_info (fi))
+ char buf[2];
+ if (addr < lim + 8)
{
- frame_extra_info_zalloc (fi, sizeof (struct frame_extra_info));
- get_frame_extra_info (fi)->from_pc = 0;
-
- if (!get_frame_pc (fi))
- {
- if (get_next_frame (fi))
- deprecated_update_frame_pc_hack (fi, h8300_frame_saved_pc (get_next_frame (fi)));
- }
- h8300_frame_init_saved_regs (fi);
+ read_memory (addr, buf, 2);
+ *pword1 = extract_signed_integer (buf, 2);
+
+ return addr + 2;
}
+ return 0;
}
/* Function: push_dummy_call
@@ -724,41 +858,6 @@
return sp;
}
-/* Function: h8300_pop_frame
- Restore the machine to the state it had before the current frame
- was created. Usually used either by the "RETURN" command, or by
- call_function_by_hand after the dummy_frame is finished. */
-
-static void
-h8300_pop_frame (void)
-{
- unsigned regno;
- struct frame_info *frame = get_current_frame ();
-
- if (deprecated_pc_in_call_dummy (get_frame_pc (frame)))
- {
- deprecated_pop_dummy_frame ();
- }
- else
- {
- for (regno = 0; regno < 8; regno++)
- {
- /* Don't forget E_SP_REGNUM is a frame_saved_regs struct is the
- actual value we want, not the address of the value we want. */
- if (deprecated_get_frame_saved_regs (frame)[regno] && regno != E_SP_REGNUM)
- write_register (regno,
- read_memory_integer
- (deprecated_get_frame_saved_regs (frame)[regno], BINWORD));
- else if (deprecated_get_frame_saved_regs (frame)[regno] && regno == E_SP_REGNUM)
- write_register (regno, get_frame_base (frame) + 2 * BINWORD);
- }
-
- /* Don't forget to update the PC too! */
- write_register (E_PC_REGNUM, get_frame_extra_info (frame)->from_pc);
- }
- flush_cached_frames ();
-}
-
/* Function: extract_return_value
Figure out where in REGBUF the called function has left its return value.
Copy that into VALBUF. Be sure to account for CPU type. */
@@ -1282,10 +1381,6 @@
set_gdbarch_pseudo_register_read (gdbarch, h8300_pseudo_register_read);
set_gdbarch_pseudo_register_write (gdbarch, h8300_pseudo_register_write);
- /* 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, deprecated_init_frame_pc_default);
-
/*
* Basic register fields and methods.
*/
@@ -1302,15 +1397,12 @@
*/
set_gdbarch_skip_prologue (gdbarch, h8300_skip_prologue);
- set_gdbarch_deprecated_frame_init_saved_regs (gdbarch,
- h8300_frame_init_saved_regs);
- set_gdbarch_deprecated_init_extra_frame_info (gdbarch,
- h8300_init_extra_frame_info);
- set_gdbarch_deprecated_frame_chain (gdbarch, h8300_frame_chain);
- set_gdbarch_deprecated_saved_pc_after_call (gdbarch,
- h8300_saved_pc_after_call);
- set_gdbarch_deprecated_frame_saved_pc (gdbarch, h8300_frame_saved_pc);
- set_gdbarch_deprecated_pop_frame (gdbarch, h8300_pop_frame);
+ /* Frame unwinder. */
+ set_gdbarch_unwind_dummy_id (gdbarch, h8300_unwind_dummy_id);
+ set_gdbarch_unwind_pc (gdbarch, h8300_unwind_pc);
+
+ /* Hook in the DWARF CFI frame unwinder. */
+ frame_unwind_append_sniffer (gdbarch, dwarf2_frame_sniffer);
/*
* Miscelany
@@ -1335,7 +1427,10 @@
/* Char is unsigned. */
set_gdbarch_char_signed (gdbarch, 0);
+ frame_unwind_append_sniffer (gdbarch, h8300_frame_sniffer);
+
return gdbarch;
+
}
extern initialize_file_ftype _initialize_h8300_tdep; /* -Wmissing-prototypes */
============================================================
--
Yoshinori Sato
<ysato@users.sourceforge.jp>