+/* 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
+m32r_frame_this_id (struct frame_info *this_frame,
+ void **this_prologue_cache, struct frame_id *this_id)
+{
+ struct m32r_unwind_cache *info
+ = m32r_frame_unwind_cache (this_frame, this_prologue_cache);
+ CORE_ADDR base;
+ CORE_ADDR func;
+ struct minimal_symbol *msym_stack;
+ struct frame_id id;
+
+ /* The FUNC is easy. */
+ func = get_frame_func (this_frame);
+
+ /* Check if the stack is empty. */
+ msym_stack = lookup_minimal_symbol ("_stack", NULL, NULL);
+ if (msym_stack && info->base == SYMBOL_VALUE_ADDRESS (msym_stack))
+ 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);
+ (*this_id) = id;
+}
+
+static struct value *
+m32r_frame_prev_register (struct frame_info *this_frame,
+ void **this_prologue_cache, int regnum)
+{
+ struct m32r_unwind_cache *info
+ = m32r_frame_unwind_cache (this_frame, this_prologue_cache);
+ return trad_frame_get_prev_register (this_frame, info->saved_regs, regnum);
+}
+
+static const struct frame_unwind m32r_frame_unwind = {
+ NORMAL_FRAME,
+ default_frame_unwind_stop_reason,
+ m32r_frame_this_id,
+ m32r_frame_prev_register,
+ NULL,
+ default_frame_sniffer
+};
+
+static CORE_ADDR
+m32r_frame_base_address (struct frame_info *this_frame, void **this_cache)
+{
+ struct m32r_unwind_cache *info
+ = m32r_frame_unwind_cache (this_frame, this_cache);
+ return info->base;
+}
+
+static const struct frame_base m32r_frame_base = {
+ &m32r_frame_unwind,
+ m32r_frame_base_address,
+ m32r_frame_base_address,
+ m32r_frame_base_address
+};
+
+/* Assuming THIS_FRAME 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
+m32r_dummy_id (struct gdbarch *gdbarch, struct frame_info *this_frame)
+{
+ CORE_ADDR sp = get_frame_register_unsigned (this_frame, M32R_SP_REGNUM);
+ return frame_id_build (sp, get_frame_pc (this_frame));
+}
+
+
+static gdbarch_init_ftype m32r_gdbarch_init;
+
+static struct gdbarch *
+m32r_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches)
+{
+ struct gdbarch *gdbarch;
+ struct gdbarch_tdep *tdep;
+
+ /* If there is already a candidate, use it. */
+ arches = gdbarch_list_lookup_by_info (arches, &info);
+ if (arches != NULL)
+ return arches->gdbarch;
+
+ /* Allocate space for the new architecture. */
+ tdep = XMALLOC (struct gdbarch_tdep);
+ gdbarch = gdbarch_alloc (&info, tdep);
+
+ set_gdbarch_read_pc (gdbarch, m32r_read_pc);
+ set_gdbarch_write_pc (gdbarch, m32r_write_pc);
+ set_gdbarch_unwind_sp (gdbarch, m32r_unwind_sp);
+
+ set_gdbarch_num_regs (gdbarch, M32R_NUM_REGS);
+ set_gdbarch_sp_regnum (gdbarch, M32R_SP_REGNUM);
+ set_gdbarch_register_name (gdbarch, m32r_register_name);
+ set_gdbarch_register_type (gdbarch, m32r_register_type);
+
+ set_gdbarch_push_dummy_call (gdbarch, m32r_push_dummy_call);
+ set_gdbarch_return_value (gdbarch, m32r_return_value);
+
+ set_gdbarch_skip_prologue (gdbarch, m32r_skip_prologue);
+ set_gdbarch_inner_than (gdbarch, core_addr_lessthan);
+ set_gdbarch_breakpoint_from_pc (gdbarch, m32r_breakpoint_from_pc);
+ set_gdbarch_memory_insert_breakpoint (gdbarch,
+ m32r_memory_insert_breakpoint);
+ set_gdbarch_memory_remove_breakpoint (gdbarch,
+ m32r_memory_remove_breakpoint);
+
+ set_gdbarch_frame_align (gdbarch, m32r_frame_align);
+
+ frame_base_set_default (gdbarch, &m32r_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_dummy_id (gdbarch, m32r_dummy_id);
+
+ /* Return the unwound PC value. */
+ set_gdbarch_unwind_pc (gdbarch, m32r_unwind_pc);
+
+ set_gdbarch_print_insn (gdbarch, print_insn_m32r);
+
+ /* Hook in ABI-specific overrides, if they have been registered. */
+ gdbarch_init_osabi (info, gdbarch);
+
+ /* Hook in the default unwinders. */
+ frame_unwind_append_unwinder (gdbarch, &m32r_frame_unwind);
+
+ /* Support simple overlay manager. */
+ set_gdbarch_overlay_update (gdbarch, simple_overlay_update);
+
+ return gdbarch;