Ejemplo n.º 1
0
Archivo: vax.c Proyecto: h4ck3rm1k3/gcc
static void
vax_output_function_prologue (FILE * file, HOST_WIDE_INT size)
{
  int regno;
  int mask = 0;

  for (regno = 0; regno < FIRST_PSEUDO_REGISTER; regno++)
    if (df_regs_ever_live_p (regno) && !call_used_regs[regno])
      mask |= 1 << regno;

  fprintf (file, "\t.word 0x%x\n", mask);

  if (dwarf2out_do_frame ())
    {
      const char *label = dwarf2out_cfi_label ();
      int offset = 0;

      for (regno = FIRST_PSEUDO_REGISTER-1; regno >= 0; --regno)
	if (df_regs_ever_live_p (regno) && !call_used_regs[regno])
	  dwarf2out_reg_save (label, regno, offset -= 4);

      dwarf2out_reg_save (label, PC_REGNUM, offset -= 4);
      dwarf2out_reg_save (label, FRAME_POINTER_REGNUM, offset -= 4);
      dwarf2out_reg_save (label, ARG_POINTER_REGNUM, offset -= 4);
      dwarf2out_def_cfa (label, FRAME_POINTER_REGNUM, -(offset - 4));
    }

  size -= STARTING_FRAME_OFFSET;
  if (size >= 64)
    asm_fprintf (file, "\tmovab %wd(%Rsp),%Rsp\n", -size);
  else if (size)
    asm_fprintf (file, "\tsubl2 $%wd,%Rsp\n", size);
}
Ejemplo n.º 2
0
static void
crx_compute_save_regs (void)
{
  unsigned int regno;

  /* initialize here so in case the function is no-return it will be -1. */
  last_reg_to_save = -1;

  /* No need to save any registers if the function never returns.  */
  if (FUNC_IS_NORETURN_P (current_function_decl))
    return;

  /* Initialize the number of bytes to be saved. */
  sum_regs = 0;

  for (regno = 0; regno < FIRST_PSEUDO_REGISTER; regno++)
    {
      if (fixed_regs[regno])
	{
	  save_regs[regno] = 0;
	  continue;
	}

      /* If this reg is used and not call-used (except RA), save it. */
      if (crx_interrupt_function_p ())
	{
	  if (!current_function_is_leaf && call_used_regs[regno])
	    /* this is a volatile reg in a non-leaf interrupt routine - save it
	     * for the sake of its sons.  */
	    save_regs[regno] = 1;

	  else if (df_regs_ever_live_p (regno))
	    /* This reg is used - save it.  */
	    save_regs[regno] = 1;
	  else
	    /* This reg is not used, and is not a volatile - don't save. */
      	    save_regs[regno] = 0;
	}
      else
	{
	  /* If this reg is used and not call-used (except RA), save it. */
	  if (df_regs_ever_live_p (regno)
	      && (!call_used_regs[regno] || regno == RETURN_ADDRESS_REGNUM))
	    save_regs[regno] = 1;
	  else
	    save_regs[regno] = 0;
	}
    }

  for (regno = 0; regno < FIRST_PSEUDO_REGISTER; regno++)
    if (save_regs[regno] == 1)
      {
	last_reg_to_save = regno;
	sum_regs += UNITS_PER_WORD;
      }
}
Ejemplo n.º 3
0
Archivo: lm32.c Proyecto: boomeer/gcc
/* Return the bytes needed to compute the frame pointer from the current
   stack pointer.  */
static HOST_WIDE_INT
lm32_compute_frame_size (int size)
{
  int regno;
  HOST_WIDE_INT total_size, locals_size, args_size, pretend_size, callee_size;
  unsigned int reg_save_mask;

  locals_size = size;
  args_size = crtl->outgoing_args_size;
  pretend_size = crtl->args.pretend_args_size;
  callee_size = 0;
  reg_save_mask = 0;

  /* Build mask that actually determines which regsiters we save
     and calculate size required to store them in the stack.  */
  for (regno = 1; regno < SP_REGNUM; regno++)
    {
      if (df_regs_ever_live_p (regno) && !call_used_regs[regno])
	{
	  reg_save_mask |= 1 << regno;
	  callee_size += UNITS_PER_WORD;
	}
    }
  if (df_regs_ever_live_p (RA_REGNUM) || ! crtl->is_leaf
      || !optimize)
    {
      reg_save_mask |= 1 << RA_REGNUM;
      callee_size += UNITS_PER_WORD;
    }
  if (!(reg_save_mask & (1 << FP_REGNUM)) && frame_pointer_needed)
    {
      reg_save_mask |= 1 << FP_REGNUM;
      callee_size += UNITS_PER_WORD;
    }

  /* Compute total frame size.  */
  total_size = pretend_size + args_size + locals_size + callee_size;

  /* Align frame to appropriate boundary.  */
  total_size = (total_size + 3) & ~3;

  /* Save computed information.  */
  current_frame_info.total_size = total_size;
  current_frame_info.callee_size = callee_size;
  current_frame_info.pretend_size = pretend_size;
  current_frame_info.locals_size = locals_size;
  current_frame_info.args_size = args_size;
  current_frame_info.reg_save_mask = reg_save_mask;

  return total_size;
}
Ejemplo n.º 4
0
Archivo: lm32.c Proyecto: boomeer/gcc
/* Support function to determine the return address of the function
   'count' frames back up the stack.  */
rtx
lm32_return_addr_rtx (int count, rtx frame)
{
  rtx r;
  if (count == 0)
    {
      if (!df_regs_ever_live_p (RA_REGNUM))
	r = gen_rtx_REG (Pmode, RA_REGNUM);
      else
	{
	  r = gen_rtx_MEM (Pmode,
			   gen_rtx_PLUS (Pmode, frame,
					 GEN_INT (-2 * UNITS_PER_WORD)));
	  set_mem_alias_set (r, get_frame_alias_set ());
	}
    }
  else if (flag_omit_frame_pointer)
    r = NULL_RTX;
  else
    {
      r = gen_rtx_MEM (Pmode,
		       gen_rtx_PLUS (Pmode, frame,
				     GEN_INT (-2 * UNITS_PER_WORD)));
      set_mem_alias_set (r, get_frame_alias_set ());
    }
  return r;
}
Ejemplo n.º 5
0
void
moxie_expand_epilogue (void)
{
  int regno;
  rtx reg;

  if (cfun->machine->callee_saved_reg_size != 0)
    {
      reg = gen_rtx_REG (Pmode, MOXIE_R12);
      if (cfun->machine->callee_saved_reg_size <= 255)
	{
	  emit_move_insn (reg, hard_frame_pointer_rtx);
	  emit_insn (gen_subsi3 
		     (reg, reg, 
		      GEN_INT (cfun->machine->callee_saved_reg_size)));
	}
      else
	{
	  emit_move_insn (reg,
			  GEN_INT (-cfun->machine->callee_saved_reg_size));
	  emit_insn (gen_addsi3 (reg, reg, hard_frame_pointer_rtx));
	}
      for (regno = FIRST_PSEUDO_REGISTER; regno-- > 0; )
	if (!fixed_regs[regno] && !call_used_regs[regno]
	    && df_regs_ever_live_p (regno))
	  {
	    rtx preg = gen_rtx_REG (Pmode, regno);
	    emit_insn (gen_movsi_pop (reg, preg));
	  }
    }

  emit_jump_insn (gen_returner ());
}
Ejemplo n.º 6
0
static void
moxie_compute_frame (void)
{
  /* For aligning the local variables.  */
  int stack_alignment = STACK_BOUNDARY / BITS_PER_UNIT;
  int padding_locals;
  int regno;

  /* Padding needed for each element of the frame.  */
  cfun->machine->local_vars_size = get_frame_size ();

  /* Align to the stack alignment.  */
  padding_locals = cfun->machine->local_vars_size % stack_alignment;
  if (padding_locals)
    padding_locals = stack_alignment - padding_locals;

  cfun->machine->local_vars_size += padding_locals;

  cfun->machine->callee_saved_reg_size = 0;

  /* Save callee-saved registers.  */
  for (regno = 0; regno < FIRST_PSEUDO_REGISTER; regno++)
    if (df_regs_ever_live_p (regno) && (! call_used_regs[regno]))
      cfun->machine->callee_saved_reg_size += 4;

  cfun->machine->size_for_adjusting_sp = 
    crtl->args.pretend_args_size
    + cfun->machine->local_vars_size 
    + (ACCUMULATE_OUTGOING_ARGS ? crtl->outgoing_args_size : 0);
}
Ejemplo n.º 7
0
/* Support function to determine the return address of the function
   'count' frames back up the stack. */
rtx
lm32_return_addr_rtx (int count, rtx frame)
{
    rtx r;
    if (count == 0)
    {
        /* *mjs* This test originally used leaf_function_p (), we now use
        the regs_ever_live test which I *think* is more accurate. */
        if (!df_regs_ever_live_p(RA_REGNUM))
        {
            r = gen_rtx_REG (Pmode, RA_REGNUM);
        }
        else
        {
            r = gen_rtx_MEM (Pmode,
                             gen_rtx_PLUS (Pmode, frame,
                                           GEN_INT(- 2 * UNITS_PER_WORD)));
            set_mem_alias_set (r, get_frame_alias_set ());
        }
    }
    else if (flag_omit_frame_pointer)
        r = NULL_RTX;
    else
    {
        r = gen_rtx_MEM (Pmode,
                         gen_rtx_PLUS (Pmode, frame,
                                       GEN_INT(- 2 * UNITS_PER_WORD)));
        set_mem_alias_set (r, get_frame_alias_set ());
    }
    return r;
}
Ejemplo n.º 8
0
int registers_to_be_saved()
{
        int i,num;
        for(i=0,num=0;i<FIRST_PSEUDO_REGISTER;i++)
        {
                if(df_regs_ever_live_p(i) && !call_used_regs[i] && !fixed_regs[i])
                        num++;
        }
        return num;
}
Ejemplo n.º 9
0
void
moxie_expand_prologue (void)
{
  int regno;
  rtx insn;

  moxie_compute_frame ();

  if (flag_stack_usage_info)
    current_function_static_stack_size = cfun->machine->size_for_adjusting_sp;

  /* Save callee-saved registers.  */
  for (regno = 0; regno < FIRST_PSEUDO_REGISTER; regno++)
    {
      if (!fixed_regs[regno] && df_regs_ever_live_p (regno) && !call_used_regs[regno])
	{
	  insn = emit_insn (gen_movsi_push (gen_rtx_REG (Pmode, regno)));
	  RTX_FRAME_RELATED_P (insn) = 1;
	}
    }

  if (cfun->machine->size_for_adjusting_sp > 0)
    {
      int i = cfun->machine->size_for_adjusting_sp; 
      while ((i >= 255) && (i <= 510))
	{
	  insn = emit_insn (gen_subsi3 (stack_pointer_rtx, 
					stack_pointer_rtx, 
					GEN_INT (255)));
	  RTX_FRAME_RELATED_P (insn) = 1;
	  i -= 255;
	}
      if (i <= 255)
	{
	  insn = emit_insn (gen_subsi3 (stack_pointer_rtx, 
					stack_pointer_rtx, 
					GEN_INT (i)));
	  RTX_FRAME_RELATED_P (insn) = 1;
	}
      else
	{
	  rtx reg = gen_rtx_REG (SImode, MOXIE_R12);
	  insn = emit_move_insn (reg, GEN_INT (i));
	  RTX_FRAME_RELATED_P (insn) = 1;
	  insn = emit_insn (gen_subsi3 (stack_pointer_rtx, 
					stack_pointer_rtx, 
					reg));
	  RTX_FRAME_RELATED_P (insn) = 1;
	}
    }
}
Ejemplo n.º 10
0
Archivo: lm32.c Proyecto: boomeer/gcc
/* Return nonzero if this function is known to have a null epilogue.
   This allows the optimizer to omit jumps to jumps if no stack
   was created.  */
int
lm32_can_use_return (void)
{
  if (!reload_completed)
    return 0;

  if (df_regs_ever_live_p (RA_REGNUM) || crtl->profile)
    return 0;

  if (lm32_compute_frame_size (get_frame_size ()) != 0)
    return 0;

  return 1;
}
Ejemplo n.º 11
0
/* Returns a number of pushed registers */
static int msp430_func_num_saved_regs (void)
{
    int i;
    int saves = 0;
    int interrupt_func_p = interrupt_function_p (current_function_decl);

    for (i = 4; i < 16; i++)
    {
        if ((df_regs_ever_live_p(i)
                && (!call_used_regs[i]
                    || interrupt_func_p))
                || (!cfun->machine->is_leaf && (call_used_regs[i] && interrupt_func_p)))
        {
            saves += 1;
        }
    }

    return saves;
}
Ejemplo n.º 12
0
void
moxie_expand_prologue (void)
{
  int regno;
  rtx insn;

  moxie_compute_frame ();

  /* Save callee-saved registers.  */
  for (regno = 0; regno < FIRST_PSEUDO_REGISTER; regno++)
    {
      if (!fixed_regs[regno] && df_regs_ever_live_p (regno) && !call_used_regs[regno])
	{
	  insn = emit_insn (gen_movsi_push (gen_rtx_REG (Pmode, regno)));
	  RTX_FRAME_RELATED_P (insn) = 1;
	}
    }

  if (cfun->machine->size_for_adjusting_sp > 0)
    {
      if (cfun->machine->size_for_adjusting_sp <= 255)
	{
	  insn = emit_insn (gen_subsi3 (stack_pointer_rtx, 
					stack_pointer_rtx, 
					GEN_INT (cfun->machine->size_for_adjusting_sp)));
	  RTX_FRAME_RELATED_P (insn) = 1;
	}
      else
	{
	  insn = 
	    emit_insn (gen_movsi 
		       (gen_rtx_REG (Pmode, MOXIE_R5), 
			GEN_INT (-cfun->machine->size_for_adjusting_sp)));
	  RTX_FRAME_RELATED_P (insn) = 1;
	  insn = emit_insn (gen_addsi3 (stack_pointer_rtx, 
					stack_pointer_rtx, 
					gen_rtx_REG (Pmode, MOXIE_R5)));
	  RTX_FRAME_RELATED_P (insn) = 1;
	}	
    }
}
Ejemplo n.º 13
0
static void
recompute_gain_for_pattern_seq (pattern_seq pseq)
{
  matching_seq mseq;
  rtx x;
  int i;
  int hascall;
  HARD_REG_SET linkregs;

  /* Initialize data.  */
  SET_HARD_REG_SET (linkregs);
  pseq->link_reg = NULL_RTX;
  pseq->abstracted_length = 0;

  pseq->gain = -(seq_call_cost - seq_jump_cost + seq_return_cost);

  /* Determine ABSTRACTED_LENGTH and COST for matching sequences of PSEQ.
     ABSTRACTED_LENGTH may be less than MATCHING_LENGTH if sequences in the
     same block overlap. */

  for (mseq = pseq->matching_seqs; mseq; mseq = mseq->next_matching_seq)
    {
      /* Determine ABSTRACTED_LENGTH.  */
      if (mseq->next_matching_seq)
        mseq->abstracted_length = (int)(mseq->next_matching_seq->idx -
                                        mseq->idx);
      else
        mseq->abstracted_length = mseq->matching_length;

      if (mseq->abstracted_length > mseq->matching_length)
        mseq->abstracted_length = mseq->matching_length;

      /* Compute the cost of sequence.  */
      RECOMPUTE_COST (mseq);

      /* If COST is big enough registers live in this matching sequence
         should not be used as a link register. Also set ABSTRACTED_LENGTH
         of PSEQ.  */
      if (mseq->cost > seq_call_cost)
        {
          clear_regs_live_in_seq (&linkregs, mseq->insn,
                                  mseq->abstracted_length);
          if (mseq->abstracted_length > pseq->abstracted_length)
            pseq->abstracted_length = mseq->abstracted_length;
        }
    }

  /* Modify ABSTRACTED_LENGTH of PSEQ if pattern sequence overlaps with one
     of the matching sequences.  */
  for (mseq = pseq->matching_seqs; mseq; mseq = mseq->next_matching_seq)
    {
      x = pseq->insn;
      for (i = 0; (i < pseq->abstracted_length) && (x != mseq->insn); i++)
        x = prev_insn_in_block (x);
      pseq->abstracted_length = i;
    }

  /* Compute the cost of pattern sequence.  */
  RECOMPUTE_COST (pseq);

  /* No gain if COST is too small.  */
  if (pseq->cost <= seq_call_cost)
  {
    pseq->gain = -1;
    return;
  }

  /* Ensure that no matching sequence is longer than the pattern sequence.  */
  for (mseq = pseq->matching_seqs; mseq; mseq = mseq->next_matching_seq)
    {
      if (mseq->abstracted_length > pseq->abstracted_length)
        {
          mseq->abstracted_length = pseq->abstracted_length;
          RECOMPUTE_COST (mseq);
        }
      /* Once the length is stabilizing the gain can be calculated.  */
      if (mseq->cost > seq_call_cost)
        pseq->gain += mseq->cost - seq_call_cost;
    }

  /* No need to do further work if there is no gain.  */
  if (pseq->gain <= 0)
    return;

  /* Should not use registers live in the pattern sequence as link register.
   */
  clear_regs_live_in_seq (&linkregs, pseq->insn, pseq->abstracted_length);

  /* Determine whether pattern sequence contains a call_insn.  */
  hascall = 0;
  x = pseq->insn;
  for (i = 0; i < pseq->abstracted_length; i++)
    {
      if (CALL_P (x))
        {
          hascall = 1;
          break;
        }
      x = prev_insn_in_block (x);
    }

  /* Should not use a register as a link register if - it is a fixed
     register, or - the sequence contains a call insn and the register is a
     call used register, or - the register needs to be saved if used in a
     function but was not used before (since saving it can invalidate already
     computed frame pointer offsets), or - the register cannot be used as a
     base register.  */

  for (i = 0; i < FIRST_PSEUDO_REGISTER; i++)
    if (fixed_regs[i]
#ifdef REGNO_OK_FOR_INDIRECT_JUMP_P
        || (!REGNO_OK_FOR_INDIRECT_JUMP_P (i, Pmode))
#else
        || (!ok_for_base_p_1 (i, Pmode, MEM, SCRATCH))
        || (!reg_class_subset_p (REGNO_REG_CLASS (i),
				 base_reg_class (VOIDmode, MEM, SCRATCH)))
#endif
        || (hascall && call_used_regs[i])
        || (!call_used_regs[i] && !df_regs_ever_live_p (i)))
      CLEAR_HARD_REG_BIT (linkregs, i);

  /* Find an appropriate register to be used as the link register.  */
  for (i = 0; i < FIRST_PSEUDO_REGISTER; i++)
    if (TEST_HARD_REG_BIT (linkregs, i))
      {
        pseq->link_reg = gen_rtx_REG (Pmode, i);
        break;
      }

  /* Abstraction is not possible if no link register is available, so set
     gain to 0.  */
  if (!pseq->link_reg)
    pseq->gain = 0;
}
Ejemplo n.º 14
0
void expand_epilogue (void)
{
    int i;
    int interrupt_func_p = cfun->machine->is_interrupt;
    int main_p = MAIN_NAME_P (DECL_NAME (current_function_decl));
    int wakeup_func_p = cfun->machine->is_wakeup;
    int cfp = cfun->machine->is_critical;
    int ree = cfun->machine->is_reenterant;
    int save_prologue_p = msp430_save_prologue_function_p (current_function_decl);
    /*int function_size;*/
    HOST_WIDE_INT size = get_frame_size();

    rtx insn;


    last_insn_address = 0;
    jump_tables_size = 0;
    epilogue_size = 0;
    /*function_size = (INSN_ADDRESSES (INSN_UID (get_last_insn ())) - INSN_ADDRESSES (INSN_UID (get_insns ())));*/

    if (cfun->machine->is_OS_task || cfun->machine->is_naked)
    {
        emit_jump_insn (gen_return ());	/* Otherwise, epilogue with 0 instruction causes a segmentation fault */
        return;
    }

    if (msp430_empty_epilogue ())
    {
        if (!return_issued)
        {
            /*fprintf (file, "\t%s\n", msp430_emit_return (NULL, NULL, NULL));*/
            emit_jump_insn (gen_return ());
            epilogue_size++;
        }
        /*fprintf (file, "\n\t/ * epilogue: not required * /\n");*/
        goto done_epilogue;
    }

    if ((cfp || interrupt_func_p) && ree)
        ree = 0;
    if (cfp && interrupt_func_p)
        cfp = 0;

    /*fprintf (file, "\n\t/ * epilogue : frame size = %d * /\n", size);*/

    if (main_p)
    {
        int totalsize = (size + 1) & ~1;
        if ((ACCUMULATE_OUTGOING_ARGS) && (!cfun->machine->is_leaf || cfun->calls_alloca) && crtl->outgoing_args_size)
            totalsize += crtl->outgoing_args_size;
        if (totalsize)
        {
            msp430_fh_add_sp_const(totalsize);
            /*fprintf (file, "\tadd\t#%d, r1\n", (size + 1) & ~1);*/
        }
        /*fprintf (file, "\tbr\t#%s\n", msp430_endup);*/
        msp430_fh_br_to_symbol_plus_offset(msp430_endup, 0);
        epilogue_size += 4;
        if (size == 1 || size == 2 || size == 4 || size == 8)
            epilogue_size--;
    }
    else
    {
        int totalsize = (size + 1) & ~1;
        if ((ACCUMULATE_OUTGOING_ARGS) && (!cfun->machine->is_leaf || cfun->calls_alloca) && crtl->outgoing_args_size)
            totalsize += crtl->outgoing_args_size;

        if (ree)
        {
            /*fprintf (file, "\teint\n");*/

            insn = emit_insn (gen_enable_interrupt());

            epilogue_size += 1;
        }

        if (totalsize)
        {
            /*fprintf (file, "\tadd\t#%d, r1\n", (size + 1) & ~1);*/
            msp430_fh_add_sp_const(totalsize);

            if (size == 1 || size == 2 || size == 4 || size == 8)
                epilogue_size += 1;
            else
                epilogue_size += 2;
        }

        if ((TARGET_SAVE_PROLOGUE || save_prologue_p)
                && !interrupt_func_p && msp430_func_num_saved_regs () > 2)
        {
            /*fprintf (file, "\tbr\t#__epilogue_restorer+%d\n",(8 - msp430_func_num_saved_regs ()) * 2);*/

            msp430_fh_br_to_symbol_plus_offset("__epilogue_restorer", (8 - msp430_func_num_saved_regs ()) * 2);

            epilogue_size += 2;
        }
        else if ((TARGET_SAVE_PROLOGUE || save_prologue_p) && interrupt_func_p)
        {
            /*fprintf (file, "\tbr\t#__epilogue_restorer_intr+%d\n", (12 - msp430_func_num_saved_regs ()) * 2);*/
            msp430_fh_br_to_symbol_plus_offset("__epilogue_restorer_intr", (12 - msp430_func_num_saved_regs ()) * 2);
        }
        else
        {
            for (i = 4; i < 16; i++)
            {
                if ((df_regs_ever_live_p(i)
                        && (!call_used_regs[i]
                            || interrupt_func_p))
                        || (!cfun->machine->is_leaf && (call_used_regs[i] && interrupt_func_p)))
                {
                    /*fprintf (file, "\tpop\tr%d\n", i);*/
                    msp430_fh_emit_pop_reg(i);
                    epilogue_size += 1;
                }
            }

            if (interrupt_func_p && wakeup_func_p)
            {
                /*fprintf (file, "\tbic\t#0xf0,0(r1)\n");*/
                msp430_fh_bic_deref_sp(0xF0);
                epilogue_size += 3;
            }
            emit_jump_insn (gen_return ());
            /*fprintf (file, "\tret\n");*/
            epilogue_size += 1;
        }
    }

    /*fprintf (file, "\t/ * epilogue end (size=%d) * /\n", epilogue_size);*/
done_epilogue:
    /*fprintf (file, "\t/ * function %s size %d (%d) * /\n", current_function_name, prologue_size + function_size + epilogue_size, function_size);*/

    msp430_commands_in_file += prologue_size + /*function_size +*/ epilogue_size;
    msp430_commands_in_prologues += prologue_size;
    msp430_commands_in_epilogues += epilogue_size;
}
Ejemplo n.º 15
0
void expand_prologue (void)
{
    int i;
    int main_p = MAIN_NAME_P (DECL_NAME (current_function_decl));
    int stack_reserve = 0;
    int offset;
    int save_prologue_p = msp430_save_prologue_function_p (current_function_decl);
    int num_saved_regs;
    HOST_WIDE_INT size = get_frame_size();

    rtx insn;	/* Last generated instruction */

    return_issued = 0;
    last_insn_address = 0;
    jump_tables_size = 0;
    prologue_size = 0;

    cfun->machine->is_naked = msp430_naked_function_p (current_function_decl);
    cfun->machine->is_interrupt = interrupt_function_p (current_function_decl);
    cfun->machine->is_OS_task = msp430_task_function_p (current_function_decl);

    cfun->machine->is_noint_hwmul = noint_hwmul_function_p (current_function_decl);
    cfun->machine->is_critical = msp430_critical_function_p(current_function_decl);
    cfun->machine->is_reenterant = msp430_reentrant_function_p(current_function_decl);
    cfun->machine->is_wakeup = wakeup_function_p (current_function_decl);
    cfun->machine->is_signal = signal_function_p (current_function_decl);


    /* check attributes compatibility */

    if ((cfun->machine->is_critical && cfun->machine->is_reenterant) || (cfun->machine->is_reenterant && cfun->machine->is_interrupt))
    {
        warning (OPT_Wattributes, "attribute 'reentrant' ignored");
        cfun->machine->is_reenterant = 0;
    }

    if (cfun->machine->is_critical && cfun->machine->is_interrupt)
    {
        warning (OPT_Wattributes, "attribute 'critical' ignored");
        cfun->machine->is_critical = 0;
    }

    if (cfun->machine->is_signal && !cfun->machine->is_interrupt)
    {
        warning (OPT_Wattributes, "attribute 'signal' has no meaning on MSP430 without 'interrupt' attribute.");
        cfun->machine->is_signal = 0;
    }

    /* naked function discards everything */
    if (cfun->machine->is_naked)
        return;

    stack_reserve = msp430_get_stack_reserve();
    offset = initial_elimination_offset (ARG_POINTER_REGNUM, STACK_POINTER_REGNUM) - 2;

    msp430_current_frame_offset = offset;

    if (cfun->machine->is_signal && cfun->machine->is_interrupt)
    {
        prologue_size += 1;

        insn = emit_insn (gen_enable_interrupt());
        /* fprintf (file, "\teint\t; enable nested interrupt\n"); */
    }

    if (main_p)
    {
        if (TARGET_NO_STACK_INIT)
        {
            if (size || stack_reserve)
            {
                /* fprintf (file, "\tsub\t#%d, r1\t", size + stack_reserve); */

                msp430_fh_sub_sp_const(size + stack_reserve);
            }

            if (frame_pointer_needed)
            {
                /* fprintf (file, "\tmov\tr1,r%d\n", FRAME_POINTER_REGNUM); */
                insn = emit_move_insn (frame_pointer_rtx, stack_pointer_rtx);
                RTX_FRAME_RELATED_P (insn) = 1;

                prologue_size += 1;
            }

            if (size)
                prologue_size += 2;
            if (size == 1 || size == 2 || size == 4 || size == 8)
                prologue_size--;
        }
        else
        {
            /*fprintf (file, "\tmov\t#(%s-%d), r1\n", msp430_init_stack, size + stack_reserve);*/
            msp430_fh_load_sp_with_sym_plus_off(msp430_init_stack, -(size + stack_reserve));

            if (frame_pointer_needed)
            {
                /* fprintf (file, "\tmov\tr1,r%d\n", FRAME_POINTER_REGNUM); */

                insn = emit_move_insn (frame_pointer_rtx, stack_pointer_rtx);
                RTX_FRAME_RELATED_P (insn) = 1;

                prologue_size += 1;
            }
            prologue_size += 2;
        }
        if ((ACCUMULATE_OUTGOING_ARGS) && (!cfun->machine->is_leaf || cfun->calls_alloca) && crtl->outgoing_args_size)
            msp430_fh_sub_sp_const(crtl->outgoing_args_size);
    }
    else	/* not a main() function */
    {
        /* Here, we've got a chance to jump to prologue saver */
        num_saved_regs = msp430_func_num_saved_regs ();

        if (!cfun->machine->is_interrupt && cfun->machine->is_critical)
        {
            prologue_size += 3;
            /*fprintf (file, "\tpush\tr2\n");
            fprintf (file, "\tdint\n");
            if (!size)
            	fprintf (file, "\tnop\n");*/

            insn = emit_insn (gen_push_sreg()); /* Pushing R2 using normal push creates a faulty INSN */
            RTX_FRAME_RELATED_P (insn) = 1;

            insn = emit_insn (gen_disable_interrupt());
            if (!size)
                insn = emit_insn (gen_nop());
        }

        if ((TARGET_SAVE_PROLOGUE || save_prologue_p)
                && !cfun->machine->is_interrupt && !arg_register_used[12] && num_saved_regs > 4)
        {
            /* TODO: Expand this as a separate INSN called "call prologue saver", having a meaning of pushing the registers and decreasing SP,
            	so that the debug info generation code will handle this correctly */

            /*fprintf (file, "\tsub\t#16, r1\n");
            fprintf (file, "\tmov\tr0, r12\n");
            fprintf (file, "\tadd\t#8, r12\n");
            fprintf (file, "\tbr\t#__prologue_saver+%d\n", (8 - num_saved_regs) * 4);*/

            msp430_fh_sub_sp_const(16);
            msp430_fh_gen_mov_pc_to_reg(12);
            msp430_fh_add_reg_const(12, 8);
            msp430_fh_br_to_symbol_plus_offset("__prologue_saver", (8 - num_saved_regs) * 4);

            if (cfun->machine->is_critical && 8 - num_saved_regs)
            {
                int n = 16 - num_saved_regs * 2;
                /*fprintf (file, "\tadd\t#%d, r1\n", n);*/
                msp430_fh_add_sp_const(n);
                if (n != 0 && n != 1 && n != 2 && n != 4 && n != 8)
                    prologue_size += 1;
            }
            else
                size -= 16 - num_saved_regs * 2;

            prologue_size += 7;
        }
        else if(!cfun->machine->is_OS_task)
        {
            for (i = 15; i >= 4; i--)
            {
                if ((df_regs_ever_live_p(i) && (!call_used_regs[i] || cfun->machine->is_interrupt)) ||
                        (!cfun->machine->is_leaf && (call_used_regs[i] && (cfun->machine->is_interrupt))))
                {
                    /*fprintf (file, "\tpush\tr%d\n", i);*/
                    msp430_fh_emit_push_reg(i);
                    prologue_size += 1;
                }
            }
        }

        if (size)
        {
            /* The next is a hack... I do not understand why, but if there
            ARG_POINTER_REGNUM and FRAME/STACK are different,
            the compiler fails to compute corresponding
            displacement */
            if (!optimize && !optimize_size
                    && df_regs_ever_live_p(ARG_POINTER_REGNUM))
            {
                int o = initial_elimination_offset (ARG_POINTER_REGNUM, STACK_POINTER_REGNUM) - size;

                /* fprintf (file, "\tmov\tr1, r%d\n", ARG_POINTER_REGNUM);
                fprintf (file, "\tadd\t#%d, r%d\n", o, ARG_POINTER_REGNUM); */

                insn = emit_move_insn (arg_pointer_rtx, stack_pointer_rtx);
                RTX_FRAME_RELATED_P (insn) = 1;
                msp430_fh_add_reg_const(ARG_POINTER_REGNUM, o);

                prologue_size += 2;
                if (o != 0 && o != 1 && o != 2 && o != 4 && o != 8)
                    prologue_size += 1;
            }

            /* adjust frame ptr... */
            if (size < 0)
            {
                int subtracted = (size + 1) & ~1;
                /*fprintf (file, "\tsub\t#%d, r1\t;	%d, fpn %d\n", subtracted, size, frame_pointer_needed);*/
                msp430_fh_sub_sp_const(subtracted);

            }
            else
            {
                int added;
                size = -size;
                added = (size + 1) & ~1;
                /*fprintf (file, "\tadd\t#%d, r1\t;    %d, fpn %d\n", (size + 1) & ~1, size, frame_pointer_needed);*/
                msp430_fh_add_sp_const(added);
            }

            if (size == 1 || size == 2 || size == 4 || size == 8)
                prologue_size += 1;
            else
                prologue_size += 2;
        }

        if (frame_pointer_needed)
        {
            /*fprintf (file, "\tmov\tr1,r%d\n", FRAME_POINTER_REGNUM);*/

            insn = emit_move_insn (frame_pointer_rtx, stack_pointer_rtx);
            RTX_FRAME_RELATED_P (insn) = 1;

            prologue_size += 1;
        }

        if ((ACCUMULATE_OUTGOING_ARGS) && (!cfun->machine->is_leaf || cfun->calls_alloca) && crtl->outgoing_args_size)
            msp430_fh_sub_sp_const(crtl->outgoing_args_size);

        /* disable interrupt for reentrant function */
        if (!cfun->machine->is_interrupt && cfun->machine->is_reenterant)
        {
            prologue_size += 1;
            /*fprintf (file, "\tdint\n");*/
            insn = emit_insn (gen_disable_interrupt());
        }
    }

    /*fprintf (file, "\t/ * prologue end (size=%d) * /\n\n", prologue_size);*/
}