/* Analyze a prologue starting at START_PC, going no further than LIMIT_PC. Fill in RESULT as appropriate. */ static void rx_analyze_prologue (CORE_ADDR start_pc, CORE_ADDR limit_pc, struct rx_prologue *result) { 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)); for (rn = 0; rn < RX_NUM_REGS; rn++) { reg[rn] = pv_register (rn, 0); 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); /* The call instruction 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]); pc = start_pc; while (pc < limit_pc) { int bytes_read; struct rx_get_opcode_byte_handle opcode_handle; RX_Opcode_Decoded opc; opcode_handle.pc = pc; bytes_read = rx_decode_opcode (pc, &opc, rx_get_opcode_byte, &opcode_handle); next_pc = pc + bytes_read; if (opc.id == RXO_pushm /* pushm r1, r2 */ && opc.op[1].type == RX_Operand_Register && opc.op[2].type == RX_Operand_Register) { int r1, r2; int r; r1 = opc.op[1].reg; r2 = opc.op[2].reg; 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]); } after_last_frame_setup_insn = next_pc; } else if (opc.id == RXO_mov /* mov.l rdst, rsrc */ && opc.op[0].type == RX_Operand_Register && opc.op[1].type == RX_Operand_Register && opc.size == RX_Long) { int rdst, rsrc; rdst = opc.op[0].reg; rsrc = opc.op[1].reg; reg[rdst] = reg[rsrc]; if (rdst == RX_FP_REGNUM && rsrc == RX_SP_REGNUM) after_last_frame_setup_insn = next_pc; } else if (opc.id == RXO_mov /* mov.l rsrc, [-SP] */ && opc.op[0].type == RX_Operand_Predec && opc.op[0].reg == RX_SP_REGNUM && opc.op[1].type == RX_Operand_Register && opc.size == RX_Long) { int rsrc; 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]); after_last_frame_setup_insn = next_pc; } else if (opc.id == RXO_add /* add #const, rsrc, rdst */ && opc.op[0].type == RX_Operand_Register && opc.op[1].type == RX_Operand_Immediate && opc.op[2].type == RX_Operand_Register) { int rdst = opc.op[0].reg; int addend = opc.op[1].addend; int rsrc = opc.op[2].reg; reg[rdst] = pv_add_constant (reg[rsrc], addend); /* Negative adjustments to the stack pointer or frame pointer are (most likely) part of the prologue. */ if ((rdst == RX_SP_REGNUM || rdst == RX_FP_REGNUM) && addend < 0) after_last_frame_setup_insn = next_pc; } else if (opc.id == RXO_mov && opc.op[0].type == RX_Operand_Indirect && opc.op[1].type == RX_Operand_Register && opc.size == RX_Long && (opc.op[0].reg == RX_SP_REGNUM || opc.op[0].reg == RX_FP_REGNUM) && (RX_R1_REGNUM <= opc.op[1].reg && opc.op[1].reg <= RX_R4_REGNUM)) { /* This moves an argument register to the stack. Don't record it, but allow it to be a part of the prologue. */ } else if (opc.id == RXO_branch && opc.op[0].type == RX_Operand_Immediate && next_pc < opc.op[0].addend) { /* When a loop appears as the first statement of a function body, gcc 4.x will use a BRA instruction to branch to the loop condition checking code. This BRA instruction is marked as part of the prologue. We therefore set next_pc to this branch target and also stop the prologue scan. The instructions at and beyond the branch target should no longer be associated with the prologue. Note that we only consider forward branches here. We presume that a forward branch is being used to skip over a loop body. A backwards branch is covered by the default case below. If we were to encounter a backwards branch, that would most likely mean that we've scanned through a loop body. We definitely want to stop the prologue scan when this happens and that is precisely what is done by the default case below. */ after_last_frame_setup_insn = opc.op[0].addend; break; /* Scan no further if we hit this case. */ } else { /* Terminate the prologue scan. */ break; } pc = next_pc; } /* Is the frame size (offset, really) a known constant? */ if (pv_is_register (reg[RX_SP_REGNUM], RX_SP_REGNUM)) result->frame_size = reg[RX_SP_REGNUM].k; /* Was the frame pointer initialized? */ if (pv_is_register (reg[RX_FP_REGNUM], RX_SP_REGNUM)) { result->has_frame_ptr = 1; result->frame_ptr_offset = reg[RX_FP_REGNUM].k; } /* Record where all the registers were saved. */ pv_area_scan (stack, check_for_saved, (void *) result); result->prologue_end = after_last_frame_setup_insn; do_cleanups (back_to); }
static void msp430_analyze_prologue (struct gdbarch *gdbarch, CORE_ADDR start_pc, CORE_ADDR limit_pc, struct msp430_prologue *result) { 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; memset (result, 0, sizeof (*result)); for (rn = 0; rn < MSP430_NUM_TOTAL_REGS; rn++) { reg[rn] = pv_register (rn, 0); result->reg_offset[rn] = 1; } stack = make_pv_area (MSP430_SP_REGNUM, gdbarch_addr_bit (gdbarch)); back_to = make_cleanup_free_pv_area (stack); /* 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]); pc = start_pc; while (pc < limit_pc) { int bytes_read; struct msp430_get_opcode_byte_handle opcode_handle; MSP430_Opcode_Decoded opc; opcode_handle.pc = pc; bytes_read = msp430_decode_opcode (pc, &opc, msp430_get_opcode_byte, &opcode_handle); next_pc = pc + bytes_read; if (opc.id == MSO_push && opc.op[0].type == MSP430_Operand_Register) { 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]); after_last_frame_setup_insn = next_pc; } else if (opc.id == MSO_push /* PUSHM */ && opc.op[0].type == MSP430_Operand_None && opc.op[1].type == MSP430_Operand_Register) { int rsrc = opc.op[1].reg; int count = opc.repeats + 1; int size = opc.size == 16 ? 2 : 4; while (count > 0) { reg[MSP430_SP_REGNUM] = pv_add_constant (reg[MSP430_SP_REGNUM], -size); pv_area_store (stack, reg[MSP430_SP_REGNUM], size, reg[rsrc]); rsrc--; count--; } after_last_frame_setup_insn = next_pc; } else if (opc.id == MSO_sub && opc.op[0].type == MSP430_Operand_Register && opc.op[0].reg == MSR_SP && opc.op[1].type == MSP430_Operand_Immediate) { int addend = opc.op[1].addend; reg[MSP430_SP_REGNUM] = pv_add_constant (reg[MSP430_SP_REGNUM], -addend); after_last_frame_setup_insn = next_pc; } else if (opc.id == MSO_mov && opc.op[0].type == MSP430_Operand_Immediate && 12 <= opc.op[0].reg && opc.op[0].reg <= 15) after_last_frame_setup_insn = next_pc; else { /* Terminate the prologue scan. */ break; } pc = next_pc; } /* Is the frame size (offset, really) a known constant? */ if (pv_is_register (reg[MSP430_SP_REGNUM], MSP430_SP_REGNUM)) result->frame_size = reg[MSP430_SP_REGNUM].k; /* Record where all the registers were saved. */ pv_area_scan (stack, check_for_saved, result); result->prologue_end = after_last_frame_setup_insn; do_cleanups (back_to); }