+2017-10-12 Tom Tromey <tom@tromey.com>
+
+ * s390-linux-tdep.c (s390_store, s390_load)
+ (s390_check_for_saved, s390_analyze_prologue): Update.
+ * rx-tdep.c (check_for_saved, rx_analyze_prologue): Update.
+ * rl78-tdep.c (rl78_analyze_prologue, check_for_saved): Update.
+ * prologue-value.h (class pv_area): Move from prologue-value.c.
+ Change names of members. Add constructor, destructor, member
+ functions.
+ (make_pv_area, free_pv_area, make_cleanup_free_pv_area)
+ (pv_area_store, pv_area_fetch, pv_area_store_would_trash)
+ (pv_area_fetch, pv_area_scan): Don't declare.
+ * prologue-value.c (struct pv_area::area_entry): Now member of
+ pv_area.
+ (struct pv_area): Move to prologue-value.h.
+ (pv_area::pv_area): Rename from make_pv_area.
+ (pv_area::~pv_area): Rename from free_pv_area.
+ (do_free_pv_area_cleanup, make_cleanup_free_pv_area): Remove.
+ (clear_entries, find_entry, overlaps, store_would_trash, store)
+ (fetch, find_reg, scan): Now member of pv_area.
+ Remove "area" argument. Update.
+ * msp430-tdep.c (check_for_saved, msp430_analyze_prologue):
+ Update.
+ * mn10300-tdep.c (push_reg, check_for_saved)
+ (mn10300_analyze_prologue): Update.
+ * mep-tdep.c (is_arg_spill, check_for_saved)
+ (mep_analyze_prologue): Update.
+ * m32c-tdep.c (m32c_pv_push, m32c_srcdest_fetch)
+ (m32c_srcdest_store, m32c_pv_enter, m32c_is_arg_spill)
+ (m32c_is_struct_return, m32c_analyze_prologue): Update.
+ * arm-tdep.c (thumb_analyze_prologue, arm_analyze_prologue):
+ Update.
+ * arc-tdep.c (arc_is_in_prologue, arc_analyze_prologue): Update.
+ * aarch64-tdep.c (aarch64_analyze_prologue): Update.
+
2017-10-12 Simon Marchi <simon.marchi@ericsson.com>
* linux-nat.h (linux_nat_set_delete_thread): New declaration.
int i;
/* Track X registers and D registers in prologue. */
pv_t regs[AARCH64_X_REGISTER_COUNT + AARCH64_D_REGISTER_COUNT];
- struct pv_area *stack;
- struct cleanup *back_to;
for (i = 0; i < AARCH64_X_REGISTER_COUNT + AARCH64_D_REGISTER_COUNT; i++)
regs[i] = pv_register (i, 0);
- stack = make_pv_area (AARCH64_SP_REGNUM, gdbarch_addr_bit (gdbarch));
- back_to = make_cleanup_free_pv_area (stack);
+ pv_area stack (AARCH64_SP_REGNUM, gdbarch_addr_bit (gdbarch));
for (; start < limit; start += 4)
{
gdb_assert (inst.operands[1].type == AARCH64_OPND_ADDR_SIMM9);
gdb_assert (!inst.operands[1].addr.offset.is_reg);
- pv_area_store (stack, pv_add_constant (regs[rn],
- inst.operands[1].addr.offset.imm),
- is64 ? 8 : 4, regs[rt]);
+ stack.store (pv_add_constant (regs[rn],
+ inst.operands[1].addr.offset.imm),
+ is64 ? 8 : 4, regs[rt]);
}
else if ((inst.opcode->iclass == ldstpair_off
|| (inst.opcode->iclass == ldstpair_indexed
/* If recording this store would invalidate the store area
(perhaps because rn is not known) then we should abandon
further prologue analysis. */
- if (pv_area_store_would_trash (stack,
- pv_add_constant (regs[rn], imm)))
+ if (stack.store_would_trash (pv_add_constant (regs[rn], imm)))
break;
- if (pv_area_store_would_trash (stack,
- pv_add_constant (regs[rn], imm + 8)))
+ if (stack.store_would_trash (pv_add_constant (regs[rn], imm + 8)))
break;
rt1 = inst.operands[0].reg.regno;
rt2 += AARCH64_X_REGISTER_COUNT;
}
- pv_area_store (stack, pv_add_constant (regs[rn], imm), 8,
- regs[rt1]);
- pv_area_store (stack, pv_add_constant (regs[rn], imm + 8), 8,
- regs[rt2]);
+ stack.store (pv_add_constant (regs[rn], imm), 8,
+ regs[rt1]);
+ stack.store (pv_add_constant (regs[rn], imm + 8), 8,
+ regs[rt2]);
if (inst.operands[2].addr.writeback)
regs[rn] = pv_add_constant (regs[rn], imm);
rt += AARCH64_X_REGISTER_COUNT;
}
- pv_area_store (stack, pv_add_constant (regs[rn], imm),
- is64 ? 8 : 4, regs[rt]);
+ stack.store (pv_add_constant (regs[rn], imm),
+ is64 ? 8 : 4, regs[rt]);
if (inst.operands[1].addr.writeback)
regs[rn] = pv_add_constant (regs[rn], imm);
}
}
if (cache == NULL)
- {
- do_cleanups (back_to);
- return start;
- }
+ return start;
if (pv_is_register (regs[AARCH64_FP_REGNUM], AARCH64_SP_REGNUM))
{
{
CORE_ADDR offset;
- if (pv_area_find_reg (stack, gdbarch, i, &offset))
+ if (stack.find_reg (gdbarch, i, &offset))
cache->saved_regs[i].addr = offset;
}
int regnum = gdbarch_num_regs (gdbarch);
CORE_ADDR offset;
- if (pv_area_find_reg (stack, gdbarch, i + AARCH64_X_REGISTER_COUNT,
- &offset))
+ if (stack.find_reg (gdbarch, i + AARCH64_X_REGISTER_COUNT,
+ &offset))
cache->saved_regs[i + regnum + AARCH64_D0_REGNUM].addr = offset;
}
- do_cleanups (back_to);
return start;
}
addr = pv_add_constant (regs[base_reg],
arc_insn_get_memory_offset (insn));
- if (pv_area_store_would_trash (stack, addr))
+ if (stack->store_would_trash (addr))
return false;
if (insn.data_size_mode != ARC_SCALING_D)
else
size = ARC_REGISTER_SIZE;
- pv_area_store (stack, addr, size, store_value);
+ stack->store (addr, size, store_value);
}
else
{
/* If this is a double store, than write N+1 register as well. */
pv_t store_value1 = regs[insn.operands[0].value];
pv_t store_value2 = regs[insn.operands[0].value + 1];
- pv_area_store (stack, addr, ARC_REGISTER_SIZE, store_value1);
- pv_area_store (stack,
- pv_add_constant (addr, ARC_REGISTER_SIZE),
- ARC_REGISTER_SIZE, store_value2);
+ stack->store (addr, ARC_REGISTER_SIZE, store_value1);
+ stack->store (pv_add_constant (addr, ARC_REGISTER_SIZE),
+ ARC_REGISTER_SIZE, store_value2);
}
else
{
pv_t store_value
= pv_constant (arc_insn_get_operand_value (insn, 0));
- pv_area_store (stack, addr, ARC_REGISTER_SIZE * 2, store_value);
+ stack->store (addr, ARC_REGISTER_SIZE * 2, store_value);
}
}
/* Assume that if the last register (closest to new SP) can be written,
then it is possible to write all of them. */
- if (pv_area_store_would_trash (stack, new_sp))
+ if (stack->store_would_trash (new_sp))
return false;
/* Current store address. */
if (is_fp_saved)
{
addr = pv_add_constant (addr, -ARC_REGISTER_SIZE);
- pv_area_store (stack, addr, ARC_REGISTER_SIZE, regs[ARC_FP_REGNUM]);
+ stack->store (addr, ARC_REGISTER_SIZE, regs[ARC_FP_REGNUM]);
}
/* Registers are stored in backward order: from GP (R26) to R13. */
for (int i = ARC_R13_REGNUM + regs_saved - 1; i >= ARC_R13_REGNUM; i--)
{
addr = pv_add_constant (addr, -ARC_REGISTER_SIZE);
- pv_area_store (stack, addr, ARC_REGISTER_SIZE, regs[i]);
+ stack->store (addr, ARC_REGISTER_SIZE, regs[i]);
}
if (is_blink_saved)
{
addr = pv_add_constant (addr, -ARC_REGISTER_SIZE);
- pv_area_store (stack, addr, ARC_REGISTER_SIZE,
- regs[ARC_BLINK_REGNUM]);
+ stack->store (addr, ARC_REGISTER_SIZE,
+ regs[ARC_BLINK_REGNUM]);
}
gdb_assert (pv_is_identical (addr, new_sp));
pv_t regs[ARC_LAST_CORE_REGNUM + 1];
for (int i = 0; i <= ARC_LAST_CORE_REGNUM; i++)
regs[i] = pv_register (i, 0);
- struct pv_area *stack = make_pv_area (ARC_SP_REGNUM,
- gdbarch_addr_bit (gdbarch));
- struct cleanup *back_to = make_cleanup_free_pv_area (stack);
+ pv_area stack (ARC_SP_REGNUM, gdbarch_addr_bit (gdbarch));
CORE_ADDR current_prologue_end = entrypoint;
/* If this instruction is in the prologue, fields in the cache will be
updated, and the saved registers mask may be updated. */
- if (!arc_is_in_prologue (gdbarch, insn, regs, stack))
+ if (!arc_is_in_prologue (gdbarch, insn, regs, &stack))
{
/* Found an instruction that is not in the prologue. */
if (arc_debug)
for (int i = 0; i <= ARC_LAST_CORE_REGNUM; i++)
{
CORE_ADDR offset;
- if (pv_area_find_reg (stack, gdbarch, i, &offset))
+ if (stack.find_reg (gdbarch, i, &offset))
cache->saved_regs[i].addr = offset;
}
}
- do_cleanups (back_to);
return current_prologue_end;
}
enum bfd_endian byte_order_for_code = gdbarch_byte_order_for_code (gdbarch);
int i;
pv_t regs[16];
- struct pv_area *stack;
- struct cleanup *back_to;
CORE_ADDR offset;
CORE_ADDR unrecognized_pc = 0;
for (i = 0; i < 16; i++)
regs[i] = pv_register (i, 0);
- stack = make_pv_area (ARM_SP_REGNUM, gdbarch_addr_bit (gdbarch));
- back_to = make_cleanup_free_pv_area (stack);
+ pv_area stack (ARM_SP_REGNUM, gdbarch_addr_bit (gdbarch));
while (start < limit)
{
int regno;
int mask;
- if (pv_area_store_would_trash (stack, regs[ARM_SP_REGNUM]))
+ if (stack.store_would_trash (regs[ARM_SP_REGNUM]))
break;
/* Bits 0-7 contain a mask for registers R0-R7. Bit 8 says
{
regs[ARM_SP_REGNUM] = pv_add_constant (regs[ARM_SP_REGNUM],
-4);
- pv_area_store (stack, regs[ARM_SP_REGNUM], 4, regs[regno]);
+ stack.store (regs[ARM_SP_REGNUM], 4, regs[regno]);
}
}
else if ((insn & 0xff80) == 0xb080) /* sub sp, #imm */
offset = (insn & 0xff) << 2;
addr = pv_add_constant (regs[ARM_SP_REGNUM], offset);
- if (pv_area_store_would_trash (stack, addr))
+ if (stack.store_would_trash (addr))
break;
- pv_area_store (stack, addr, 4, regs[regno]);
+ stack.store (addr, 4, regs[regno]);
}
else if ((insn & 0xf800) == 0x6000) /* str rd, [rn, #off] */
{
offset = bits (insn, 6, 10) << 2;
addr = pv_add_constant (regs[rn], offset);
- if (pv_area_store_would_trash (stack, addr))
+ if (stack.store_would_trash (addr))
break;
- pv_area_store (stack, addr, 4, regs[rd]);
+ stack.store (addr, 4, regs[rd]);
}
else if (((insn & 0xf800) == 0x7000 /* strb Rd, [Rn, #off] */
|| (insn & 0xf800) == 0x8000) /* strh Rd, [Rn, #off] */
pv_t addr = regs[bits (insn, 0, 3)];
int regno;
- if (pv_area_store_would_trash (stack, addr))
+ if (stack.store_would_trash (addr))
break;
/* Calculate offsets of saved registers. */
if (inst2 & (1 << regno))
{
addr = pv_add_constant (addr, -4);
- pv_area_store (stack, addr, 4, regs[regno]);
+ stack.store (addr, 4, regs[regno]);
}
if (insn & 0x0020)
else
addr = pv_add_constant (addr, -offset);
- if (pv_area_store_would_trash (stack, addr))
+ if (stack.store_would_trash (addr))
break;
- pv_area_store (stack, addr, 4, regs[regno1]);
- pv_area_store (stack, pv_add_constant (addr, 4),
- 4, regs[regno2]);
+ stack.store (addr, 4, regs[regno1]);
+ stack.store (pv_add_constant (addr, 4),
+ 4, regs[regno2]);
if (insn & 0x0020)
regs[bits (insn, 0, 3)] = addr;
else
addr = pv_add_constant (addr, -offset);
- if (pv_area_store_would_trash (stack, addr))
+ if (stack.store_would_trash (addr))
break;
- pv_area_store (stack, addr, 4, regs[regno]);
+ stack.store (addr, 4, regs[regno]);
if (inst2 & 0x0100)
regs[bits (insn, 0, 3)] = addr;
offset = inst2 & 0xfff;
addr = pv_add_constant (regs[bits (insn, 0, 3)], offset);
- if (pv_area_store_would_trash (stack, addr))
+ if (stack.store_would_trash (addr))
break;
- pv_area_store (stack, addr, 4, regs[regno]);
+ stack.store (addr, 4, regs[regno]);
}
else if ((insn & 0xffd0) == 0xf880 /* str{bh}.w Rt,[Rn,#imm] */
unrecognized_pc = start;
if (cache == NULL)
- {
- do_cleanups (back_to);
- return unrecognized_pc;
- }
+ return unrecognized_pc;
if (pv_is_register (regs[ARM_FP_REGNUM], ARM_SP_REGNUM))
{
}
for (i = 0; i < 16; i++)
- if (pv_area_find_reg (stack, gdbarch, i, &offset))
+ if (stack.find_reg (gdbarch, i, &offset))
cache->saved_regs[i].addr = offset;
- do_cleanups (back_to);
return unrecognized_pc;
}
int regno;
CORE_ADDR offset, current_pc;
pv_t regs[ARM_FPS_REGNUM];
- struct pv_area *stack;
- struct cleanup *back_to;
CORE_ADDR unrecognized_pc = 0;
/* Search the prologue looking for instructions that set up the
for (regno = 0; regno < ARM_FPS_REGNUM; regno++)
regs[regno] = pv_register (regno, 0);
- stack = make_pv_area (ARM_SP_REGNUM, gdbarch_addr_bit (gdbarch));
- back_to = make_cleanup_free_pv_area (stack);
+ pv_area stack (ARM_SP_REGNUM, gdbarch_addr_bit (gdbarch));
for (current_pc = prologue_start;
current_pc < prologue_end;
else if ((insn & 0xffff0fff) == 0xe52d0004) /* str Rd,
[sp, #-4]! */
{
- if (pv_area_store_would_trash (stack, regs[ARM_SP_REGNUM]))
+ if (stack.store_would_trash (regs[ARM_SP_REGNUM]))
break;
regs[ARM_SP_REGNUM] = pv_add_constant (regs[ARM_SP_REGNUM], -4);
- pv_area_store (stack, regs[ARM_SP_REGNUM], 4,
- regs[bits (insn, 12, 15)]);
+ stack.store (regs[ARM_SP_REGNUM], 4,
+ regs[bits (insn, 12, 15)]);
continue;
}
else if ((insn & 0xffff0000) == 0xe92d0000)
{
int mask = insn & 0xffff;
- if (pv_area_store_would_trash (stack, regs[ARM_SP_REGNUM]))
+ if (stack.store_would_trash (regs[ARM_SP_REGNUM]))
break;
/* Calculate offsets of saved registers. */
{
regs[ARM_SP_REGNUM]
= pv_add_constant (regs[ARM_SP_REGNUM], -4);
- pv_area_store (stack, regs[ARM_SP_REGNUM], 4, regs[regno]);
+ stack.store (regs[ARM_SP_REGNUM], 4, regs[regno]);
}
}
else if ((insn & 0xffff0000) == 0xe54b0000 /* strb rx,[r11,#-n] */
[sp, -#c]! */
&& gdbarch_tdep (gdbarch)->have_fpa_registers)
{
- if (pv_area_store_would_trash (stack, regs[ARM_SP_REGNUM]))
+ if (stack.store_would_trash (regs[ARM_SP_REGNUM]))
break;
regs[ARM_SP_REGNUM] = pv_add_constant (regs[ARM_SP_REGNUM], -12);
regno = ARM_F0_REGNUM + ((insn >> 12) & 0x07);
- pv_area_store (stack, regs[ARM_SP_REGNUM], 12, regs[regno]);
+ stack.store (regs[ARM_SP_REGNUM], 12, regs[regno]);
}
else if ((insn & 0xffbf0fff) == 0xec2d0200 /* sfmfd f0, 4,
[sp!] */
int n_saved_fp_regs;
unsigned int fp_start_reg, fp_bound_reg;
- if (pv_area_store_would_trash (stack, regs[ARM_SP_REGNUM]))
+ if (stack.store_would_trash (regs[ARM_SP_REGNUM]))
break;
if ((insn & 0x800) == 0x800) /* N0 is set */
for (; fp_start_reg < fp_bound_reg; fp_start_reg++)
{
regs[ARM_SP_REGNUM] = pv_add_constant (regs[ARM_SP_REGNUM], -12);
- pv_area_store (stack, regs[ARM_SP_REGNUM], 12,
- regs[fp_start_reg++]);
+ stack.store (regs[ARM_SP_REGNUM], 12,
+ regs[fp_start_reg++]);
}
}
else if ((insn & 0xff000000) == 0xeb000000 && cache == NULL) /* bl */
cache->framesize = framesize;
for (regno = 0; regno < ARM_FPS_REGNUM; regno++)
- if (pv_area_find_reg (stack, gdbarch, regno, &offset))
+ if (stack.find_reg (gdbarch, regno, &offset))
cache->saved_regs[regno].addr = offset;
}
fprintf_unfiltered (gdb_stdlog, "Prologue scan stopped at %s\n",
paddress (gdbarch, unrecognized_pc));
- do_cleanups (back_to);
return unrecognized_pc;
}
static int
m32c_pv_push (struct m32c_pv_state *state, pv_t value, int size)
{
- if (pv_area_store_would_trash (state->stack, state->sp))
+ if (state->stack->store_would_trash (state->sp))
return 1;
state->sp = pv_add_constant (state->sp, -size);
- pv_area_store (state->stack, state->sp, size, value);
+ state->stack->store (state->sp, size, value);
return 0;
}
m32c_srcdest_fetch (struct m32c_pv_state *state, struct srcdest loc, int size)
{
if (loc.kind == srcdest_mem)
- return pv_area_fetch (state->stack, loc.addr, size);
+ return state->stack->fetch (loc.addr, size);
else if (loc.kind == srcdest_partial_reg)
return pv_unknown ();
else
{
if (loc.kind == srcdest_mem)
{
- if (pv_area_store_would_trash (state->stack, loc.addr))
+ if (state->stack->store_would_trash (loc.addr))
return 1;
- pv_area_store (state->stack, loc.addr, size, value);
+ state->stack->store (loc.addr, size, value);
}
else if (loc.kind == srcdest_partial_reg)
*loc.reg = pv_unknown ();
/* If simulating this store would require us to forget
everything we know about the stack frame in the name of
accuracy, it would be better to just quit now. */
- if (pv_area_store_would_trash (state->stack, state->sp))
+ if (state->stack->store_would_trash (state->sp))
return 1;
if (m32c_pv_push (state, state->fb, tdep->push_addr_bytes))
return (m32c_is_arg_reg (st, value)
&& loc.kind == srcdest_mem
&& pv_is_register (loc.addr, tdep->sp->num)
- && ! pv_area_find_reg (st->stack, st->arch, value.reg, 0));
+ && ! st->stack->find_reg (st->arch, value.reg, 0));
}
/* Return non-zero if a store of VALUE to LOC is probably
struct gdbarch_tdep *tdep = gdbarch_tdep (st->arch);
return (m32c_is_1st_arg_reg (st, value)
- && !pv_area_find_reg (st->stack, st->arch, value.reg, 0)
+ && !st->stack->find_reg (st->arch, value.reg, 0)
&& loc.kind == srcdest_reg
&& (pv_is_register (*loc.reg, tdep->a0->num)
|| pv_is_register (*loc.reg, tdep->a1->num)));
/* Function for finding saved registers in a 'struct pv_area'; we pass
- this to pv_area_scan.
+ this to pv_area::scan.
If VALUE is a saved register, ADDR says it was saved at a constant
offset from the frame base, and SIZE indicates that the whole
struct gdbarch_tdep *tdep = gdbarch_tdep (arch);
unsigned long mach = gdbarch_bfd_arch_info (arch)->mach;
CORE_ADDR after_last_frame_related_insn;
- struct cleanup *back_to;
struct m32c_pv_state st;
st.arch = arch;
st.fb = pv_register (tdep->fb->num, 0);
st.sp = pv_register (tdep->sp->num, 0);
st.pc = pv_register (tdep->pc->num, 0);
- st.stack = make_pv_area (tdep->sp->num, gdbarch_addr_bit (arch));
- back_to = make_cleanup_free_pv_area (st.stack);
+ pv_area stack (tdep->sp->num, gdbarch_addr_bit (arch));
+ st.stack = &stack;
/* Record that the call instruction has saved the return address on
the stack. */
prologue->kind = prologue_first_frame;
/* Record where all the registers were saved. */
- pv_area_scan (st.stack, check_for_saved, (void *) prologue);
+ st.stack->scan (check_for_saved, (void *) prologue);
prologue->prologue_end = after_last_frame_related_insn;
-
- do_cleanups (back_to);
}
{
return (is_arg_reg (value)
&& pv_is_register (addr, MEP_SP_REGNUM)
- && ! pv_area_find_reg (stack, gdbarch, value.reg, 0));
+ && ! stack->find_reg (gdbarch, value.reg, 0));
}
/* Function for finding saved registers in a 'struct pv_area'; we pass
- this to pv_area_scan.
+ this to pv_area::scan.
If VALUE is a saved register, ADDR says it was saved at a constant
offset from the frame base, and SIZE indicates that the whole
int rn;
int found_lp = 0;
pv_t reg[MEP_NUM_REGS];
- struct pv_area *stack;
- struct cleanup *back_to;
CORE_ADDR after_last_frame_setup_insn = start_pc;
memset (result, 0, sizeof (*result));
result->reg_offset[rn] = 1;
}
- stack = make_pv_area (MEP_SP_REGNUM, gdbarch_addr_bit (gdbarch));
- back_to = make_cleanup_free_pv_area (stack);
+ pv_area stack (MEP_SP_REGNUM, gdbarch_addr_bit (gdbarch));
pc = start_pc;
while (pc < limit_pc)
/* If simulating this store would require us to forget
everything we know about the stack frame in the name of
accuracy, it would be better to just quit now. */
- if (pv_area_store_would_trash (stack, reg[rm]))
+ if (stack.store_would_trash (reg[rm]))
break;
- if (is_arg_spill (gdbarch, reg[rn], reg[rm], stack))
+ if (is_arg_spill (gdbarch, reg[rn], reg[rm], &stack))
after_last_frame_setup_insn = next_pc;
- pv_area_store (stack, reg[rm], 4, reg[rn]);
+ stack.store (reg[rm], 4, reg[rn]);
}
else if (IS_SW_IMMD (insn))
{
/* If simulating this store would require us to forget
everything we know about the stack frame in the name of
accuracy, it would be better to just quit now. */
- if (pv_area_store_would_trash (stack, addr))
+ if (stack.store_would_trash (addr))
break;
- if (is_arg_spill (gdbarch, reg[rn], addr, stack))
+ if (is_arg_spill (gdbarch, reg[rn], addr, &stack))
after_last_frame_setup_insn = next_pc;
- pv_area_store (stack, addr, 4, reg[rn]);
+ stack.store (addr, 4, reg[rn]);
}
else if (IS_MOV (insn))
{
: (gdb_assert (IS_SW (insn)), 4));
pv_t addr = pv_add_constant (reg[rm], disp);
- if (pv_area_store_would_trash (stack, addr))
+ if (stack.store_would_trash (addr))
break;
- if (is_arg_spill (gdbarch, reg[rn], addr, stack))
+ if (is_arg_spill (gdbarch, reg[rn], addr, &stack))
after_last_frame_setup_insn = next_pc;
- pv_area_store (stack, addr, size, reg[rn]);
+ stack.store (addr, size, reg[rn]);
}
else if (IS_LDC (insn))
{
int offset = LW_OFFSET (insn);
pv_t addr = pv_add_constant (reg[rm], offset);
- reg[rn] = pv_area_fetch (stack, addr, 4);
+ reg[rn] = stack.fetch (addr, 4);
}
else if (IS_BRA (insn) && BRA_DISP (insn) > 0)
{
}
/* Record where all the registers were saved. */
- pv_area_scan (stack, check_for_saved, (void *) result);
+ stack.scan (check_for_saved, (void *) result);
result->prologue_end = after_last_frame_setup_insn;
-
- do_cleanups (back_to);
}
push_reg (pv_t *regs, struct pv_area *stack, int regnum)
{
regs[E_SP_REGNUM] = pv_add_constant (regs[E_SP_REGNUM], -4);
- pv_area_store (stack, regs[E_SP_REGNUM], 4, regs[regnum]);
+ stack->store (regs[E_SP_REGNUM], 4, regs[regnum]);
}
/* Translate an "r" register number extracted from an instruction encoding
return E_E0_REGNUM + rreg;
}
-/* Find saved registers in a 'struct pv_area'; we pass this to pv_area_scan.
+/* Find saved registers in a 'struct pv_area'; we pass this to pv_area::scan.
If VALUE is a saved register, ADDR says it was saved at a constant
offset from the frame base, and SIZE indicates that the whole
CORE_ADDR pc;
int rn;
pv_t regs[MN10300_MAX_NUM_REGS];
- struct pv_area *stack;
- struct cleanup *back_to;
CORE_ADDR after_last_frame_setup_insn = start_pc;
int am33_mode = AM33_MODE (gdbarch);
regs[rn] = pv_register (rn, 0);
result->reg_offset[rn] = 1;
}
- stack = make_pv_area (E_SP_REGNUM, gdbarch_addr_bit (gdbarch));
- back_to = make_cleanup_free_pv_area (stack);
+ pv_area stack (E_SP_REGNUM, gdbarch_addr_bit (gdbarch));
- /* The typical call instruction will have saved the return address on the
- stack. Space for the return address has already been preallocated in
- the caller's frame. It's possible, such as when using -mrelax with gcc
- that other registers were saved as well. If this happens, we really
- have no chance of deciphering the frame. DWARF info can save the day
- when this happens. */
- pv_area_store (stack, regs[E_SP_REGNUM], 4, regs[E_PC_REGNUM]);
+ /* The typical call instruction will have saved the return address on the
+ stack. Space for the return address has already been preallocated in
+ the caller's frame. It's possible, such as when using -mrelax with gcc
+ that other registers were saved as well. If this happens, we really
+ have no chance of deciphering the frame. DWARF info can save the day
+ when this happens. */
+ stack.store (regs[E_SP_REGNUM], 4, regs[E_PC_REGNUM]);
pc = start_pc;
while (pc < limit_pc)
if ((save_mask & movm_exreg0_bit) && am33_mode)
{
- push_reg (regs, stack, E_E2_REGNUM);
- push_reg (regs, stack, E_E3_REGNUM);
+ push_reg (regs, &stack, E_E2_REGNUM);
+ push_reg (regs, &stack, E_E3_REGNUM);
}
if ((save_mask & movm_exreg1_bit) && am33_mode)
{
- push_reg (regs, stack, E_E4_REGNUM);
- push_reg (regs, stack, E_E5_REGNUM);
- push_reg (regs, stack, E_E6_REGNUM);
- push_reg (regs, stack, E_E7_REGNUM);
+ push_reg (regs, &stack, E_E4_REGNUM);
+ push_reg (regs, &stack, E_E5_REGNUM);
+ push_reg (regs, &stack, E_E6_REGNUM);
+ push_reg (regs, &stack, E_E7_REGNUM);
}
if ((save_mask & movm_exother_bit) && am33_mode)
{
- push_reg (regs, stack, E_E0_REGNUM);
- push_reg (regs, stack, E_E1_REGNUM);
- push_reg (regs, stack, E_MDRQ_REGNUM);
- push_reg (regs, stack, E_MCRH_REGNUM);
- push_reg (regs, stack, E_MCRL_REGNUM);
- push_reg (regs, stack, E_MCVF_REGNUM);
+ push_reg (regs, &stack, E_E0_REGNUM);
+ push_reg (regs, &stack, E_E1_REGNUM);
+ push_reg (regs, &stack, E_MDRQ_REGNUM);
+ push_reg (regs, &stack, E_MCRH_REGNUM);
+ push_reg (regs, &stack, E_MCRL_REGNUM);
+ push_reg (regs, &stack, E_MCVF_REGNUM);
}
if (save_mask & movm_d2_bit)
- push_reg (regs, stack, E_D2_REGNUM);
+ push_reg (regs, &stack, E_D2_REGNUM);
if (save_mask & movm_d3_bit)
- push_reg (regs, stack, E_D3_REGNUM);
+ push_reg (regs, &stack, E_D3_REGNUM);
if (save_mask & movm_a2_bit)
- push_reg (regs, stack, E_A2_REGNUM);
+ push_reg (regs, &stack, E_A2_REGNUM);
if (save_mask & movm_a3_bit)
- push_reg (regs, stack, E_A3_REGNUM);
+ push_reg (regs, &stack, E_A3_REGNUM);
if (save_mask & movm_other_bit)
{
- push_reg (regs, stack, E_D0_REGNUM);
- push_reg (regs, stack, E_D1_REGNUM);
- push_reg (regs, stack, E_A0_REGNUM);
- push_reg (regs, stack, E_A1_REGNUM);
- push_reg (regs, stack, E_MDR_REGNUM);
- push_reg (regs, stack, E_LIR_REGNUM);
- push_reg (regs, stack, E_LAR_REGNUM);
+ push_reg (regs, &stack, E_D0_REGNUM);
+ push_reg (regs, &stack, E_D1_REGNUM);
+ push_reg (regs, &stack, E_A0_REGNUM);
+ push_reg (regs, &stack, E_A1_REGNUM);
+ push_reg (regs, &stack, E_MDR_REGNUM);
+ push_reg (regs, &stack, E_LIR_REGNUM);
+ push_reg (regs, &stack, E_LAR_REGNUM);
/* The `other' bit leaves a blank area of four bytes at
the beginning of its block of saved registers, making
it 32 bytes long in total. */
rN = buf[0] & 0x0f;
fsM = (Y << 4) | sM;
- pv_area_store (stack, regs[translate_rreg (rN)], 4,
- regs[E_FS0_REGNUM + fsM]);
+ stack.store (regs[translate_rreg (rN)], 4,
+ regs[E_FS0_REGNUM + fsM]);
pc += 3;
}
sM = (buf[0] & 0xf0) >> 4;
fsM = (Y << 4) | sM;
- pv_area_store (stack, regs[E_SP_REGNUM], 4,
- regs[E_FS0_REGNUM + fsM]);
+ stack.store (regs[E_SP_REGNUM], 4,
+ regs[E_FS0_REGNUM + fsM]);
pc += 3;
}
Z = (buf[1] & 0x02) >> 1;
fsM = (Z << 4) | sM;
- pv_area_store (stack,
- pv_add (regs[translate_rreg (rN)],
- regs[translate_rreg (rI)]),
- 4, regs[E_FS0_REGNUM + fsM]);
+ stack.store (pv_add (regs[translate_rreg (rN)],
+ regs[translate_rreg (rI)]),
+ 4, regs[E_FS0_REGNUM + fsM]);
pc += 4;
}
fsM = (Y << 4) | sM;
d8 = extract_signed_integer (&buf[1], 1, byte_order);
- pv_area_store (stack,
- pv_add_constant (regs[translate_rreg (rN)], d8),
- 4, regs[E_FS0_REGNUM + fsM]);
+ stack.store (pv_add_constant (regs[translate_rreg (rN)], d8),
+ 4, regs[E_FS0_REGNUM + fsM]);
pc += 4;
}
fsM = (Y << 4) | sM;
d24 = extract_signed_integer (&buf[1], 3, byte_order);
- pv_area_store (stack,
- pv_add_constant (regs[translate_rreg (rN)], d24),
- 4, regs[E_FS0_REGNUM + fsM]);
+ stack.store (pv_add_constant (regs[translate_rreg (rN)], d24),
+ 4, regs[E_FS0_REGNUM + fsM]);
pc += 6;
}
fsM = (Y << 4) | sM;
d32 = extract_signed_integer (&buf[1], 4, byte_order);
- pv_area_store (stack,
- pv_add_constant (regs[translate_rreg (rN)], d32),
- 4, regs[E_FS0_REGNUM + fsM]);
+ stack.store (pv_add_constant (regs[translate_rreg (rN)], d32),
+ 4, regs[E_FS0_REGNUM + fsM]);
pc += 7;
}
fsM = (Y << 4) | sM;
d8 = extract_signed_integer (&buf[1], 1, byte_order);
- pv_area_store (stack,
- pv_add_constant (regs[E_SP_REGNUM], d8),
- 4, regs[E_FS0_REGNUM + fsM]);
+ stack.store (pv_add_constant (regs[E_SP_REGNUM], d8),
+ 4, regs[E_FS0_REGNUM + fsM]);
pc += 4;
}
fsM = (Y << 4) | sM;
d24 = extract_signed_integer (&buf[1], 3, byte_order);
- pv_area_store (stack,
- pv_add_constant (regs[E_SP_REGNUM], d24),
- 4, regs[E_FS0_REGNUM + fsM]);
+ stack.store (pv_add_constant (regs[E_SP_REGNUM], d24),
+ 4, regs[E_FS0_REGNUM + fsM]);
pc += 6;
}
fsM = (Y << 4) | sM;
d32 = extract_signed_integer (&buf[1], 4, byte_order);
- pv_area_store (stack,
- pv_add_constant (regs[E_SP_REGNUM], d32),
- 4, regs[E_FS0_REGNUM + fsM]);
+ stack.store (pv_add_constant (regs[E_SP_REGNUM], d32),
+ 4, regs[E_FS0_REGNUM + fsM]);
pc += 7;
}
rN_regnum = translate_rreg (rN);
- pv_area_store (stack, regs[rN_regnum], 4,
- regs[E_FS0_REGNUM + fsM]);
+ stack.store (regs[rN_regnum], 4,
+ regs[E_FS0_REGNUM + fsM]);
regs[rN_regnum] = pv_add_constant (regs[rN_regnum], 4);
pc += 3;
rN_regnum = translate_rreg (rN);
- pv_area_store (stack, regs[rN_regnum], 4, regs[E_FS0_REGNUM + fsM]);
+ stack.store (regs[rN_regnum], 4, regs[E_FS0_REGNUM + fsM]);
regs[rN_regnum] = pv_add_constant (regs[rN_regnum], imm8);
pc += 4;
rN_regnum = translate_rreg (rN);
- pv_area_store (stack, regs[rN_regnum], 4, regs[E_FS0_REGNUM + fsM]);
+ stack.store (regs[rN_regnum], 4, regs[E_FS0_REGNUM + fsM]);
regs[rN_regnum] = pv_add_constant (regs[rN_regnum], imm24);
pc += 6;
rN_regnum = translate_rreg (rN);
- pv_area_store (stack, regs[rN_regnum], 4, regs[E_FS0_REGNUM + fsM]);
+ stack.store (regs[rN_regnum], 4, regs[E_FS0_REGNUM + fsM]);
regs[rN_regnum] = pv_add_constant (regs[rN_regnum], imm32);
pc += 7;
}
/* Record where all the registers were saved. */
- pv_area_scan (stack, check_for_saved, (void *) result);
+ stack.scan (check_for_saved, (void *) result);
result->prologue_end = after_last_frame_setup_insn;
-
- do_cleanups (back_to);
}
/* Function: skip_prologue
}
/* Function for finding saved registers in a 'struct pv_area'; this
- function is passed to pv_area_scan.
+ function is passed to pv_area::scan.
If VALUE is a saved register, ADDR says it was saved at a constant
offset from the frame base, and SIZE indicates that the whole
CORE_ADDR pc, next_pc;
int rn;
pv_t reg[MSP430_NUM_TOTAL_REGS];
- struct pv_area *stack;
- struct cleanup *back_to;
CORE_ADDR after_last_frame_setup_insn = start_pc;
int code_model = gdbarch_tdep (gdbarch)->code_model;
int sz;
result->reg_offset[rn] = 1;
}
- stack = make_pv_area (MSP430_SP_REGNUM, gdbarch_addr_bit (gdbarch));
- back_to = make_cleanup_free_pv_area (stack);
+ pv_area stack (MSP430_SP_REGNUM, gdbarch_addr_bit (gdbarch));
/* The call instruction has saved the return address on the stack. */
sz = code_model == MSP_LARGE_CODE_MODEL ? 4 : 2;
reg[MSP430_SP_REGNUM] = pv_add_constant (reg[MSP430_SP_REGNUM], -sz);
- pv_area_store (stack, reg[MSP430_SP_REGNUM], sz, reg[MSP430_PC_REGNUM]);
+ stack.store (reg[MSP430_SP_REGNUM], sz, reg[MSP430_PC_REGNUM]);
pc = start_pc;
while (pc < limit_pc)
int rsrc = opc.op[0].reg;
reg[MSP430_SP_REGNUM] = pv_add_constant (reg[MSP430_SP_REGNUM], -2);
- pv_area_store (stack, reg[MSP430_SP_REGNUM], 2, reg[rsrc]);
+ stack.store (reg[MSP430_SP_REGNUM], 2, reg[rsrc]);
after_last_frame_setup_insn = next_pc;
}
else if (opc.id == MSO_push /* PUSHM */
{
reg[MSP430_SP_REGNUM]
= pv_add_constant (reg[MSP430_SP_REGNUM], -size);
- pv_area_store (stack, reg[MSP430_SP_REGNUM], size, reg[rsrc]);
+ stack.store (reg[MSP430_SP_REGNUM], size, reg[rsrc]);
rsrc--;
count--;
}
result->frame_size = reg[MSP430_SP_REGNUM].k;
/* Record where all the registers were saved. */
- pv_area_scan (stack, check_for_saved, result);
+ stack.scan (check_for_saved, result);
result->prologue_end = after_last_frame_setup_insn;
-
- do_cleanups (back_to);
}
/* Implement the "skip_prologue" gdbarch method. */
The entry with the lowest offset simply follows the entry with the
highest offset. Entries may abut, but never overlap. The area's
'entry' pointer points to an arbitrary node in the ring. */
-struct area_entry
+struct pv_area::area_entry
{
/* Links in the doubly-linked ring. */
struct area_entry *prev, *next;
};
-struct pv_area
-{
- /* This area's base register. */
- int base_reg;
-
- /* The mask to apply to addresses, to make the wrap-around happen at
- the right place. */
- CORE_ADDR addr_mask;
-
- /* An element of the doubly-linked ring of entries, or zero if we
- have none. */
- struct area_entry *entry;
-};
+/* See prologue-value.h. */
-
-struct pv_area *
-make_pv_area (int base_reg, int addr_bit)
+pv_area::pv_area (int base_reg, int addr_bit)
+ : m_base_reg (base_reg),
+ /* Remember that shift amounts equal to the type's width are
+ undefined. */
+ m_addr_mask (((((CORE_ADDR) 1 << (addr_bit - 1)) - 1) << 1) | 1),
+ m_entry (nullptr)
{
- struct pv_area *a = XNEW (struct pv_area);
-
- memset (a, 0, sizeof (*a));
-
- a->base_reg = base_reg;
- a->entry = 0;
-
- /* Remember that shift amounts equal to the type's width are
- undefined. */
- a->addr_mask = ((((CORE_ADDR) 1 << (addr_bit - 1)) - 1) << 1) | 1;
-
- return a;
}
+/* See prologue-value.h. */
-/* Delete all entries from AREA. */
-static void
-clear_entries (struct pv_area *area)
+void
+pv_area::clear_entries ()
{
- struct area_entry *e = area->entry;
+ struct area_entry *e = m_entry;
if (e)
{
xfree (e);
e = next;
}
- while (e != area->entry);
+ while (e != m_entry);
- area->entry = 0;
+ m_entry = 0;
}
}
-void
-free_pv_area (struct pv_area *area)
+pv_area::~pv_area ()
{
- clear_entries (area);
- xfree (area);
+ clear_entries ();
}
-static void
-do_free_pv_area_cleanup (void *arg)
-{
- free_pv_area ((struct pv_area *) arg);
-}
-
-
-struct cleanup *
-make_cleanup_free_pv_area (struct pv_area *area)
-{
- return make_cleanup (do_free_pv_area_cleanup, (void *) area);
-}
-
+/* See prologue-value.h. */
int
-pv_area_store_would_trash (struct pv_area *area, pv_t addr)
+pv_area::store_would_trash (pv_t addr)
{
/* It may seem odd that pvk_constant appears here --- after all,
that's the case where we know the most about the address! But
constants. */
return (addr.kind == pvk_unknown
|| addr.kind == pvk_constant
- || (addr.kind == pvk_register && addr.reg != area->base_reg));
+ || (addr.kind == pvk_register && addr.reg != m_base_reg));
}
-/* Return a pointer to the first entry we hit in AREA starting at
- OFFSET and going forward.
-
- This may return zero, if AREA has no entries.
+/* See prologue-value.h. */
- And since the entries are a ring, this may return an entry that
- entirely precedes OFFSET. This is the correct behavior: depending
- on the sizes involved, we could still overlap such an area, with
- wrap-around. */
-static struct area_entry *
-find_entry (struct pv_area *area, CORE_ADDR offset)
+struct pv_area::area_entry *
+pv_area::find_entry (CORE_ADDR offset)
{
- struct area_entry *e = area->entry;
+ struct area_entry *e = m_entry;
if (! e)
return 0;
with wrap-around. We have to subtract offset from both sides to
make sure both things we're comparing are on the same side of the
discontinuity. */
- while (((e->next->offset - offset) & area->addr_mask)
- < ((e->offset - offset) & area->addr_mask))
+ while (((e->next->offset - offset) & m_addr_mask)
+ < ((e->offset - offset) & m_addr_mask))
e = e->next;
/* If the previous entry would be better than the current one, then
scan backwards. */
- while (((e->prev->offset - offset) & area->addr_mask)
- < ((e->offset - offset) & area->addr_mask))
+ while (((e->prev->offset - offset) & m_addr_mask)
+ < ((e->offset - offset) & m_addr_mask))
e = e->prev;
/* In case there's some locality to the searches, set the area's
pointer to the entry we've found. */
- area->entry = e;
+ m_entry = e;
return e;
}
-/* Return non-zero if the SIZE bytes at OFFSET would overlap ENTRY;
- return zero otherwise. AREA is the area to which ENTRY belongs. */
-static int
-overlaps (struct pv_area *area,
- struct area_entry *entry,
- CORE_ADDR offset,
- CORE_ADDR size)
+/* See prologue-value.h. */
+
+int
+pv_area::overlaps (struct area_entry *entry, CORE_ADDR offset, CORE_ADDR size)
{
/* Think carefully about wrap-around before simplifying this. */
- return (((entry->offset - offset) & area->addr_mask) < size
- || ((offset - entry->offset) & area->addr_mask) < entry->size);
+ return (((entry->offset - offset) & m_addr_mask) < size
+ || ((offset - entry->offset) & m_addr_mask) < entry->size);
}
+/* See prologue-value.h. */
+
void
-pv_area_store (struct pv_area *area,
- pv_t addr,
- CORE_ADDR size,
- pv_t value)
+pv_area::store (pv_t addr, CORE_ADDR size, pv_t value)
{
/* Remove any (potentially) overlapping entries. */
- if (pv_area_store_would_trash (area, addr))
- clear_entries (area);
+ if (store_would_trash (addr))
+ clear_entries ();
else
{
CORE_ADDR offset = addr.k;
- struct area_entry *e = find_entry (area, offset);
+ struct area_entry *e = find_entry (offset);
/* Delete all entries that we would overlap. */
- while (e && overlaps (area, e, offset, size))
+ while (e && overlaps (e, offset, size))
{
struct area_entry *next = (e->next == e) ? 0 : e->next;
/* Move the area's pointer to the next remaining entry. This
will also zero the pointer if we've deleted all the entries. */
- area->entry = e;
+ m_entry = e;
}
- /* Now, there are no entries overlapping us, and area->entry is
+ /* Now, there are no entries overlapping us, and m_entry is
either zero or pointing at the closest entry after us. We can
just insert ourselves before that.
e->size = size;
e->value = value;
- if (area->entry)
+ if (m_entry)
{
- e->prev = area->entry->prev;
- e->next = area->entry;
+ e->prev = m_entry->prev;
+ e->next = m_entry;
e->prev->next = e->next->prev = e;
}
else
{
e->prev = e->next = e;
- area->entry = e;
+ m_entry = e;
}
}
}
+/* See prologue-value.h. */
+
pv_t
-pv_area_fetch (struct pv_area *area, pv_t addr, CORE_ADDR size)
+pv_area::fetch (pv_t addr, CORE_ADDR size)
{
/* If we have no entries, or we can't decide how ADDR relates to the
entries we do have, then the value is unknown. */
- if (! area->entry
- || pv_area_store_would_trash (area, addr))
+ if (! m_entry
+ || store_would_trash (addr))
return pv_unknown ();
else
{
CORE_ADDR offset = addr.k;
- struct area_entry *e = find_entry (area, offset);
+ struct area_entry *e = find_entry (offset);
/* If this entry exactly matches what we're looking for, then
we're set. Otherwise, say it's unknown. */
}
+/* See prologue-value.h. */
+
int
-pv_area_find_reg (struct pv_area *area,
- struct gdbarch *gdbarch,
- int reg,
- CORE_ADDR *offset_p)
+pv_area::find_reg (struct gdbarch *gdbarch, int reg, CORE_ADDR *offset_p)
{
- struct area_entry *e = area->entry;
+ struct area_entry *e = m_entry;
if (e)
do
e = e->next;
}
- while (e != area->entry);
+ while (e != m_entry);
return 0;
}
+/* See prologue-value.h. */
+
void
-pv_area_scan (struct pv_area *area,
- void (*func) (void *closure,
- pv_t addr,
- CORE_ADDR size,
- pv_t value),
- void *closure)
+pv_area::scan (void (*func) (void *closure,
+ pv_t addr,
+ CORE_ADDR size,
+ pv_t value),
+ void *closure)
{
- struct area_entry *e = area->entry;
+ struct area_entry *e = m_entry;
pv_t addr;
addr.kind = pvk_register;
- addr.reg = area->base_reg;
+ addr.reg = m_base_reg;
if (e)
do
func (closure, addr, e->size, e->value);
e = e->next;
}
- while (e != area->entry);
+ while (e != m_entry);
}
int *i);
-/* A 'struct pv_area' keeps track of values stored in a particular
- region of memory. */
-struct pv_area;
-
-/* Create a new area, tracking stores relative to the original value
- of BASE_REG. If BASE_REG is SP, then this effectively records the
- contents of the stack frame: the original value of the SP is the
- frame's CFA, or some constant offset from it.
-
- Stores to constant addresses, unknown addresses, or to addresses
- relative to registers other than BASE_REG will trash this area; see
- pv_area_store_would_trash.
-
- To check whether a pointer refers to this area, only the low
- ADDR_BIT bits will be compared. */
-struct pv_area *make_pv_area (int base_reg, int addr_bit);
-
-/* Free AREA. */
-void free_pv_area (struct pv_area *area);
-
-
-/* Register a cleanup to free AREA. */
-struct cleanup *make_cleanup_free_pv_area (struct pv_area *area);
-
-
-/* Store the SIZE-byte value VALUE at ADDR in AREA.
-
- If ADDR is not relative to the same base register we used in
- creating AREA, then we can't tell which values here the stored
- value might overlap, and we'll have to mark everything as
- unknown. */
-void pv_area_store (struct pv_area *area,
- pv_t addr,
- CORE_ADDR size,
- pv_t value);
-
-/* Return the SIZE-byte value at ADDR in AREA. This may return
- pv_unknown (). */
-pv_t pv_area_fetch (struct pv_area *area, pv_t addr, CORE_ADDR size);
-
-/* Return true if storing to address ADDR in AREA would force us to
- mark the contents of the entire area as unknown. This could happen
- if, say, ADDR is unknown, since we could be storing anywhere. Or,
- it could happen if ADDR is relative to a different register than
- the other stores base register, since we don't know the relative
- values of the two registers.
-
- If you've reached such a store, it may be better to simply stop the
- prologue analysis, and return the information you've gathered,
- instead of losing all that information, most of which is probably
- okay. */
-int pv_area_store_would_trash (struct pv_area *area, pv_t addr);
-
-
-/* Search AREA for the original value of REGISTER. If we can't find
- it, return zero; if we can find it, return a non-zero value, and if
- OFFSET_P is non-zero, set *OFFSET_P to the register's offset within
- AREA. GDBARCH is the architecture of which REGISTER is a member.
-
- In the worst case, this takes time proportional to the number of
- items stored in AREA. If you plan to gather a lot of information
- about registers saved in AREA, consider calling pv_area_scan
- instead, and collecting all your information in one pass. */
-int pv_area_find_reg (struct pv_area *area,
- struct gdbarch *gdbarch,
- int reg,
- CORE_ADDR *offset_p);
-
-
-/* For every part of AREA whose value we know, apply FUNC to CLOSURE,
- the value's address, its size, and the value itself. */
-void pv_area_scan (struct pv_area *area,
- void (*func) (void *closure,
- pv_t addr,
- CORE_ADDR size,
- pv_t value),
- void *closure);
-
+/* A 'pv_area' keeps track of values stored in a particular region of
+ memory. */
+class pv_area
+{
+public:
+
+ /* Create a new area, tracking stores relative to the original value
+ of BASE_REG. If BASE_REG is SP, then this effectively records the
+ contents of the stack frame: the original value of the SP is the
+ frame's CFA, or some constant offset from it.
+
+ Stores to constant addresses, unknown addresses, or to addresses
+ relative to registers other than BASE_REG will trash this area; see
+ pv_area::store_would_trash.
+
+ To check whether a pointer refers to this area, only the low
+ ADDR_BIT bits will be compared. */
+ pv_area (int base_reg, int addr_bit);
+
+ ~pv_area ();
+
+ DISABLE_COPY_AND_ASSIGN (pv_area);
+
+ /* Store the SIZE-byte value VALUE at ADDR in AREA.
+
+ If ADDR is not relative to the same base register we used in
+ creating AREA, then we can't tell which values here the stored
+ value might overlap, and we'll have to mark everything as
+ unknown. */
+ void store (pv_t addr,
+ CORE_ADDR size,
+ pv_t value);
+
+ /* Return the SIZE-byte value at ADDR in AREA. This may return
+ pv_unknown (). */
+ pv_t fetch (pv_t addr, CORE_ADDR size);
+
+ /* Return true if storing to address ADDR in AREA would force us to
+ mark the contents of the entire area as unknown. This could happen
+ if, say, ADDR is unknown, since we could be storing anywhere. Or,
+ it could happen if ADDR is relative to a different register than
+ the other stores base register, since we don't know the relative
+ values of the two registers.
+
+ If you've reached such a store, it may be better to simply stop the
+ prologue analysis, and return the information you've gathered,
+ instead of losing all that information, most of which is probably
+ okay. */
+ int store_would_trash (pv_t addr);
+
+ /* Search AREA for the original value of REGISTER. If we can't find
+ it, return zero; if we can find it, return a non-zero value, and if
+ OFFSET_P is non-zero, set *OFFSET_P to the register's offset within
+ AREA. GDBARCH is the architecture of which REGISTER is a member.
+
+ In the worst case, this takes time proportional to the number of
+ items stored in AREA. If you plan to gather a lot of information
+ about registers saved in AREA, consider calling pv_area::scan
+ instead, and collecting all your information in one pass. */
+ int find_reg (struct gdbarch *gdbarch, int reg, CORE_ADDR *offset_p);
+
+
+ /* For every part of AREA whose value we know, apply FUNC to CLOSURE,
+ the value's address, its size, and the value itself. */
+ void scan (void (*func) (void *closure,
+ pv_t addr,
+ CORE_ADDR size,
+ pv_t value),
+ void *closure);
+
+private:
+
+ struct area_entry;
+
+ /* Delete all entries from AREA. */
+ void clear_entries ();
+
+ /* Return a pointer to the first entry we hit in AREA starting at
+ OFFSET and going forward.
+
+ This may return zero, if AREA has no entries.
+
+ And since the entries are a ring, this may return an entry that
+ entirely precedes OFFSET. This is the correct behavior: depending
+ on the sizes involved, we could still overlap such an area, with
+ wrap-around. */
+ struct area_entry *find_entry (CORE_ADDR offset);
+
+ /* Return non-zero if the SIZE bytes at OFFSET would overlap ENTRY;
+ return zero otherwise. AREA is the area to which ENTRY belongs. */
+ int overlaps (struct area_entry *entry,
+ CORE_ADDR offset,
+ CORE_ADDR size);
+
+ /* This area's base register. */
+ int m_base_reg;
+
+ /* The mask to apply to addresses, to make the wrap-around happen at
+ the right place. */
+ CORE_ADDR m_addr_mask;
+
+ /* An element of the doubly-linked ring of entries, or zero if we
+ have none. */
+ struct area_entry *m_entry;
+};
#endif /* PROLOGUE_VALUE_H */
}
/* Function for finding saved registers in a 'struct pv_area'; this
- function is passed to pv_area_scan.
+ function is passed to pv_area::scan.
If VALUE is a saved register, ADDR says it was saved at a constant
offset from the frame base, and SIZE indicates that the whole
CORE_ADDR pc, next_pc;
int rn;
pv_t reg[RL78_NUM_TOTAL_REGS];
- struct pv_area *stack;
- struct cleanup *back_to;
CORE_ADDR after_last_frame_setup_insn = start_pc;
int bank = 0;
result->reg_offset[rn] = 1;
}
- stack = make_pv_area (RL78_SP_REGNUM, gdbarch_addr_bit (target_gdbarch ()));
- back_to = make_cleanup_free_pv_area (stack);
+ pv_area stack (RL78_SP_REGNUM, gdbarch_addr_bit (target_gdbarch ()));
/* The call instruction has saved the return address on the stack. */
reg[RL78_SP_REGNUM] = pv_add_constant (reg[RL78_SP_REGNUM], -4);
- pv_area_store (stack, reg[RL78_SP_REGNUM], 4, reg[RL78_PC_REGNUM]);
+ stack.store (reg[RL78_SP_REGNUM], 4, reg[RL78_PC_REGNUM]);
pc = start_pc;
while (pc < limit_pc)
&& opc.op[1].type == RL78_Operand_Register)
{
int rsrc = (bank * RL78_REGS_PER_BANK)
- + 2 * (opc.op[1].reg - RL78_Reg_AX);
+ + 2 * (opc.op[1].reg - RL78_Reg_AX);
reg[RL78_SP_REGNUM] = pv_add_constant (reg[RL78_SP_REGNUM], -1);
- pv_area_store (stack, reg[RL78_SP_REGNUM], 1, reg[rsrc]);
+ stack.store (reg[RL78_SP_REGNUM], 1, reg[rsrc]);
reg[RL78_SP_REGNUM] = pv_add_constant (reg[RL78_SP_REGNUM], -1);
- pv_area_store (stack, reg[RL78_SP_REGNUM], 1, reg[rsrc + 1]);
+ stack.store (reg[RL78_SP_REGNUM], 1, reg[rsrc + 1]);
after_last_frame_setup_insn = next_pc;
}
else if (opc.id == RLO_sub
result->frame_size = reg[RL78_SP_REGNUM].k;
/* Record where all the registers were saved. */
- pv_area_scan (stack, check_for_saved, (void *) result);
+ stack.scan (check_for_saved, (void *) result);
result->prologue_end = after_last_frame_setup_insn;
-
- do_cleanups (back_to);
}
/* Implement the "addr_bits_remove" gdbarch method. */
/* Function for finding saved registers in a 'struct pv_area'; this
- function is passed to pv_area_scan.
+ function is passed to pv_area::scan.
If VALUE is a saved register, ADDR says it was saved at a constant
offset from the frame base, and SIZE indicates that the whole
CORE_ADDR pc, next_pc;
int rn;
pv_t reg[RX_NUM_REGS];
- struct pv_area *stack;
- struct cleanup *back_to;
CORE_ADDR after_last_frame_setup_insn = start_pc;
memset (result, 0, sizeof (*result));
result->reg_offset[rn] = 1;
}
- stack = make_pv_area (RX_SP_REGNUM, gdbarch_addr_bit (target_gdbarch ()));
- back_to = make_cleanup_free_pv_area (stack);
+ pv_area stack (RX_SP_REGNUM, gdbarch_addr_bit (target_gdbarch ()));
if (frame_type == RX_FRAME_TYPE_FAST_INTERRUPT)
{
if (frame_type == RX_FRAME_TYPE_EXCEPTION)
{
reg[RX_SP_REGNUM] = pv_add_constant (reg[RX_SP_REGNUM], -4);
- pv_area_store (stack, reg[RX_SP_REGNUM], 4, reg[RX_PSW_REGNUM]);
+ stack.store (reg[RX_SP_REGNUM], 4, reg[RX_PSW_REGNUM]);
}
/* The call instruction (or an exception/interrupt) has saved the return
address on the stack. */
reg[RX_SP_REGNUM] = pv_add_constant (reg[RX_SP_REGNUM], -4);
- pv_area_store (stack, reg[RX_SP_REGNUM], 4, reg[RX_PC_REGNUM]);
+ stack.store (reg[RX_SP_REGNUM], 4, reg[RX_PC_REGNUM]);
}
for (r = r2; r >= r1; r--)
{
reg[RX_SP_REGNUM] = pv_add_constant (reg[RX_SP_REGNUM], -4);
- pv_area_store (stack, reg[RX_SP_REGNUM], 4, reg[r]);
+ stack.store (reg[RX_SP_REGNUM], 4, reg[r]);
}
after_last_frame_setup_insn = next_pc;
}
rsrc = opc.op[1].reg;
reg[RX_SP_REGNUM] = pv_add_constant (reg[RX_SP_REGNUM], -4);
- pv_area_store (stack, reg[RX_SP_REGNUM], 4, reg[rsrc]);
+ stack.store (reg[RX_SP_REGNUM], 4, reg[rsrc]);
after_last_frame_setup_insn = next_pc;
}
else if (opc.id == RXO_add /* add #const, rsrc, rdst */
}
/* Record where all the registers were saved. */
- pv_area_scan (stack, check_for_saved, (void *) result);
+ stack.scan (check_for_saved, (void *) result);
result->prologue_end = after_last_frame_setup_insn;
-
- do_cleanups (back_to);
}
/* Check whether we are storing a register into the stack. */
- if (!pv_area_store_would_trash (data->stack, addr))
- pv_area_store (data->stack, addr, size, value);
+ if (!data->stack->store_would_trash (addr))
+ data->stack->store (addr, size, value);
/* Note: If this is some store we cannot identify, you might think we
}
/* Check whether we are accessing one of our save slots. */
- return pv_area_fetch (data->stack, addr, size);
+ return data->stack->fetch (addr, size);
}
/* Function for finding saved registers in a 'struct pv_area'; we pass
- this to pv_area_scan.
+ this to pv_area::scan.
If VALUE is a saved register, ADDR says it was saved at a constant
offset from the frame base, and SIZE indicates that the whole
/* The address of the next instruction after that. */
CORE_ADDR next_pc;
+ pv_area stack (S390_SP_REGNUM, gdbarch_addr_bit (gdbarch));
+ scoped_restore restore_stack = make_scoped_restore (&data->stack, &stack);
+
/* Set up everything's initial value. */
{
int i;
- data->stack = make_pv_area (S390_SP_REGNUM, gdbarch_addr_bit (gdbarch));
-
/* For the purpose of prologue tracking, we consider the GPR size to
be equal to the ABI word size, even if it is actually larger
(i.e. when running a 32-bit binary under a 64-bit kernel). */
}
/* Record where all the registers were saved. */
- pv_area_scan (data->stack, s390_check_for_saved, data);
-
- free_pv_area (data->stack);
- data->stack = NULL;
+ data->stack->scan (s390_check_for_saved, data);
return result;
}