diff options
Diffstat (limited to 'gdb/d10v-tdep.c')
-rw-r--r-- | gdb/d10v-tdep.c | 137 |
1 files changed, 68 insertions, 69 deletions
diff --git a/gdb/d10v-tdep.c b/gdb/d10v-tdep.c index 5cbdddcdce5..0fe222ec2fe 100644 --- a/gdb/d10v-tdep.c +++ b/gdb/d10v-tdep.c @@ -616,8 +616,11 @@ struct d10v_unwind_cache CORE_ADDR base; int size; CORE_ADDR *saved_regs; - LONGEST next_addr; - LONGEST r11_addr; + /* How far the SP and r11 (FP) have been offset from the start of + the stack frame (as defined by the previous frame's stack + pointer). */ + LONGEST sp_offset; + LONGEST r11_offset; int uses_frame; void **regs; }; @@ -632,8 +635,8 @@ prologue_find_regs (struct d10v_unwind_cache *info, unsigned short op, if ((op & 0x7E1F) == 0x6C1F) { n = (op & 0x1E0) >> 5; - info->next_addr -= 2; - info->saved_regs[n] = info->next_addr; + info->sp_offset -= 2; + info->saved_regs[n] = info->sp_offset; return 1; } @@ -641,9 +644,9 @@ prologue_find_regs (struct d10v_unwind_cache *info, unsigned short op, else if ((op & 0x7E3F) == 0x6E1F) { n = (op & 0x1E0) >> 5; - info->next_addr -= 4; - info->saved_regs[n] = info->next_addr; - info->saved_regs[n + 1] = info->next_addr + 2; + info->sp_offset -= 4; + info->saved_regs[n] = info->sp_offset; + info->saved_regs[n + 1] = info->sp_offset + 2; return 1; } @@ -653,7 +656,7 @@ prologue_find_regs (struct d10v_unwind_cache *info, unsigned short op, n = (op & 0x1E) >> 1; if (n == 0) n = 16; - info->next_addr -= n; + info->sp_offset -= n; return 1; } @@ -661,7 +664,7 @@ prologue_find_regs (struct d10v_unwind_cache *info, unsigned short op, if (op == 0x417E) { info->uses_frame = 1; - info->r11_addr = info->next_addr; + info->r11_offset = info->sp_offset; return 1; } @@ -669,7 +672,7 @@ prologue_find_regs (struct d10v_unwind_cache *info, unsigned short op, if ((op & 0x7E1F) == 0x6816) { n = (op & 0x1E0) >> 5; - info->saved_regs[n] = info->r11_addr; + info->saved_regs[n] = info->r11_offset; return 1; } @@ -681,7 +684,7 @@ prologue_find_regs (struct d10v_unwind_cache *info, unsigned short op, if ((op & 0x7E1F) == 0x681E) { n = (op & 0x1E0) >> 5; - info->saved_regs[n] = info->next_addr; + info->saved_regs[n] = info->sp_offset; return 1; } @@ -689,8 +692,8 @@ prologue_find_regs (struct d10v_unwind_cache *info, unsigned short op, if ((op & 0x7E3F) == 0x3A1E) { n = (op & 0x1E0) >> 5; - info->saved_regs[n] = info->next_addr; - info->saved_regs[n + 1] = info->next_addr + 2; + info->saved_regs[n] = info->sp_offset; + info->saved_regs[n + 1] = info->sp_offset + 2; return 1; } @@ -708,8 +711,8 @@ d10v_frame_unwind_cache (struct frame_info *next_frame, void **this_cache) { CORE_ADDR pc; - ULONGEST sp; - ULONGEST base; + ULONGEST prev_sp; + ULONGEST this_base; unsigned long op; unsigned short op1, op2; int i; @@ -724,7 +727,7 @@ d10v_frame_unwind_cache (struct frame_info *next_frame, info->size = 0; - info->next_addr = 0; + info->sp_offset = 0; pc = get_pc_function_start (frame_pc_unwind (next_frame)); @@ -739,22 +742,22 @@ d10v_frame_unwind_cache (struct frame_info *next_frame, { /* add3 sp,sp,n */ short n = op & 0xFFFF; - info->next_addr += n; + info->sp_offset += n; } else if ((op & 0x3F0F0000) == 0x340F0000) { /* st rn, @(offset,sp) */ short offset = op & 0xFFFF; short n = (op >> 20) & 0xF; - info->saved_regs[n] = info->next_addr + offset; + info->saved_regs[n] = info->sp_offset + offset; } else if ((op & 0x3F1F0000) == 0x350F0000) { /* st2w rn, @(offset,sp) */ short offset = op & 0xFFFF; short n = (op >> 20) & 0xF; - info->saved_regs[n] = info->next_addr + offset; - info->saved_regs[n + 1] = info->next_addr + offset + 2; + info->saved_regs[n] = info->sp_offset + offset; + info->saved_regs[n + 1] = info->sp_offset + offset + 2; } else break; @@ -779,52 +782,50 @@ d10v_frame_unwind_cache (struct frame_info *next_frame, pc += 4; } - info->size = -info->next_addr; + info->size = -info->sp_offset; - /* Compute the frame's base. */ + /* Compute the frame's base, and the previous frame's SP. */ if (info->uses_frame) { - /* The SP was moved into 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, FP_REGNUM, &base); + /* 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, FP_REGNUM, &this_base); /* The FP points at the last saved register. Adjust the FP back to before the first saved register giving the SP. */ - sp = base + info->size; + prev_sp = this_base + info->size; } else if (info->saved_regs[SP_REGNUM]) { /* The SP was saved (which is very unusual), the frame base is just the PREV's frame's TOP-OF-STACK. */ - base = read_memory_unsigned_integer (info->saved_regs[SP_REGNUM], - register_size (current_gdbarch, - SP_REGNUM)); - sp = base; + this_base = read_memory_unsigned_integer (info->saved_regs[SP_REGNUM], + register_size (current_gdbarch, + SP_REGNUM)); + prev_sp = this_base; } else { /* Assume that the FP is this frame's SP but with that pushed stack space added back. */ - frame_unwind_unsigned_register (next_frame, SP_REGNUM, &base); - sp = base + info->size; + frame_unwind_unsigned_register (next_frame, SP_REGNUM, &this_base); + prev_sp = this_base + info->size; } - info->base = d10v_make_daddr (base); - sp = d10v_make_daddr (sp); + info->base = d10v_make_daddr (this_base); + prev_sp = d10v_make_daddr (prev_sp); /* Adjust all the saved registers so that they contain addresses and not offsets. */ for (i = 0; i < NUM_REGS - 1; i++) - { - if (info->saved_regs[i]) - { - info->saved_regs[i] = (sp + info->saved_regs[i]); - } - } + if (info->saved_regs[i]) + { + info->saved_regs[i] = (prev_sp + info->saved_regs[i]); + } /* The SP_REGNUM is special. Instead of the address of the SP, the previous frame's SP value is saved. */ - info->saved_regs[SP_REGNUM] = sp; + info->saved_regs[SP_REGNUM] = prev_sp; return info; } @@ -1432,22 +1433,12 @@ display_trace (int low, int high) } } - static CORE_ADDR -d10v_frame_pc_unwind (struct frame_info *next_frame, - void **this_cache) +d10v_unwind_pc (struct gdbarch *gdbarch, struct frame_info *next_frame) { - /* FIXME: This shouldn't be needed. Instead single per-architecture - method should be called for all frames. */ - CORE_ADDR lr; - struct d10v_unwind_cache *info - = d10v_frame_unwind_cache (next_frame, this_cache); - void *buffer = alloca (max_register_size (current_gdbarch)); - saved_regs_unwind (next_frame, info->saved_regs, LR_REGNUM, buffer); - lr = extract_unsigned_integer (buffer, register_size (current_gdbarch, - LR_REGNUM)); - return d10v_make_iaddr (lr); - + ULONGEST pc; + frame_unwind_unsigned_register (next_frame, PC_REGNUM, &pc); + return d10v_make_iaddr (pc); } /* Given the next frame, determine the address of this function's @@ -1587,18 +1578,6 @@ d10v_frame_register_unwind (struct frame_info *next_frame, lvalp, addrp, realnump, bufferp); } - -static struct frame_id -d10v_unwind_dummy_id (struct gdbarch *gdbarch, struct frame_info *next_frame) -{ - ULONGEST base; - struct frame_id id; - id.pc = frame_pc_unwind (next_frame); - frame_unwind_unsigned_register (next_frame, SP_REGNUM, &base); - id.base = d10v_make_daddr (base); - return id; -} - static void d10v_frame_pop (struct frame_info *next_frame, void **this_cache, struct regcache *regcache) @@ -1635,7 +1614,6 @@ d10v_frame_pop (struct frame_info *next_frame, void **this_cache, static struct frame_unwind d10v_frame_unwind = { d10v_frame_pop, - d10v_frame_pc_unwind, d10v_frame_id_unwind, d10v_frame_register_unwind }; @@ -1646,6 +1624,22 @@ d10v_frame_p (CORE_ADDR pc) return &d10v_frame_unwind; } +/* 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 +d10v_unwind_dummy_id (struct gdbarch *gdbarch, struct frame_info *next_frame) +{ + ULONGEST base; + struct frame_id id; + id.pc = frame_pc_unwind (next_frame); + frame_unwind_unsigned_register (next_frame, SP_REGNUM, &base); + id.base = d10v_make_daddr (base); + return id; +} + static gdbarch_init_ftype d10v_gdbarch_init; static struct gdbarch * @@ -1782,9 +1776,14 @@ d10v_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches) set_gdbarch_print_registers_info (gdbarch, d10v_print_registers_info); frame_unwind_append_predicate (gdbarch, d10v_frame_p); + + /* Methods for saving / extracting a dummy frame's ID. */ set_gdbarch_unwind_dummy_id (gdbarch, d10v_unwind_dummy_id); set_gdbarch_save_dummy_frame_tos (gdbarch, generic_save_dummy_frame_tos); + /* Return the unwound PC value. */ + set_gdbarch_unwind_pc (gdbarch, d10v_unwind_pc); + return gdbarch; } |