Exemple #1
0
/* 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);
}