void generic_pop_current_frame (void (*popper) (struct frame_info * frame)) { struct frame_info *frame = get_current_frame (); if (PC_IN_CALL_DUMMY (frame->pc, frame->frame, frame->frame)) generic_pop_dummy_frame (); else (*popper) (frame); }
void microblaze_pop_frame (struct frame_info *fi) { int rn; CORE_ADDR func_addr, func_end, addr; enum microblaze_instr op; int insn, rd, ra, rb, imm; int status; char *name; int offset = 0; /* offset that the return instruction specifies */ /* Find the start and end of this function. */ /* siva/9/19/05: pop frame was not computing this offset. copied code from microblaze_fix_call_dummy to find the return insn & the offset */ status = find_pc_partial_function (fi->pc, &name, &func_addr, &func_end); for (addr = func_addr; addr < func_end; addr += INST_WORD_SIZE) { /* Start decoding the function looking for rtsd */ insn = get_insn (addr); op = microblaze_decode_insn (insn, &rd, &ra, &rb, &imm); /* Check for return. */ if (IS_RETURN(op)) { offset = imm; break; } } if (PC_IN_CALL_DUMMY (fi->pc, fi->frame, fi->frame)) generic_pop_dummy_frame (); else { /* Write out the PC we saved. */ write_register (PC_REGNUM, FRAME_SAVED_PC (fi) + offset); /* Restore any saved registers. */ for (rn = 0; rn < NUM_REGS; rn++) { if (fi->saved_regs[rn] != 0) { ULONGEST value; value = read_memory_unsigned_integer (fi->saved_regs[rn], REGISTER_SIZE); write_register (rn, value); } } /* Actually cut back the stack. */ write_register (SP_REGNUM, FRAME_FP (fi)); } /* Finally, throw away any cached frame information. */ flush_cached_frames (); }