Пример #1
0
void
moxie_expand_epilogue (void)
{
  int regno;
  rtx insn, reg, cfa_restores = NULL;

  if (cfun->machine->callee_saved_reg_size != 0)
    {
      reg = gen_rtx_REG (Pmode, MOXIE_R5);
      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);
	    insn = emit_insn (gen_movsi_pop (reg, preg));
	  }
    }

  emit_jump_insn (gen_returner ());
}
Пример #2
0
static bool
nds32_expand_setmem_loop_v3m (rtx dstmem, rtx size, rtx value)
{
  rtx base_reg = copy_to_mode_reg (Pmode, XEXP (dstmem, 0));
  rtx need_align_bytes = gen_reg_rtx (SImode);
  rtx last_2_bit = gen_reg_rtx (SImode);
  rtx byte_loop_base = gen_reg_rtx (SImode);
  rtx byte_loop_size = gen_reg_rtx (SImode);
  rtx remain_size = gen_reg_rtx (SImode);
  rtx new_base_reg;
  rtx value4byte, value4doubleword;
  rtx byte_mode_size;
  rtx last_byte_loop_label = gen_label_rtx ();

  size = force_reg (SImode, size);

  value4doubleword = nds32_gen_dup_8_byte_to_double_word_value (value);
  value4byte = simplify_gen_subreg (QImode, value4doubleword, DImode,
				    subreg_lowpart_offset (QImode, DImode));

  emit_move_insn (byte_loop_size, size);
  emit_move_insn (byte_loop_base, base_reg);

  /* Jump to last byte loop if size is less than 16.  */
  emit_cmp_and_jump_insns (size, gen_int_mode (16, SImode), LE, NULL,
			   SImode, 1, last_byte_loop_label);

  /* Make sure align to 4 byte first since v3m can't unalign access.  */
  emit_insn (gen_andsi3 (last_2_bit,
			 base_reg,
			 gen_int_mode (0x3, SImode)));

  emit_insn (gen_subsi3 (need_align_bytes,
			 gen_int_mode (4, SImode),
			 last_2_bit));

  /* Align to 4 byte. */
  new_base_reg = emit_setmem_byte_loop (base_reg,
					need_align_bytes,
					value4byte,
					true);

  /* Calculate remain size. */
  emit_insn (gen_subsi3 (remain_size, size, need_align_bytes));

  /* Set memory word by word. */
  byte_mode_size = emit_setmem_doubleword_loop (new_base_reg,
						remain_size,
						value4doubleword);

  emit_move_insn (byte_loop_base, new_base_reg);
  emit_move_insn (byte_loop_size, byte_mode_size);

  emit_label (last_byte_loop_label);

  /* And set memory for remain bytes. */
  emit_setmem_byte_loop (byte_loop_base, byte_loop_size, value4byte, false);
  return true;
}
Пример #3
0
bool
nds32_expand_strlen (rtx result, rtx str,
		     rtx target_char, rtx align ATTRIBUTE_UNUSED)
{
  rtx base_reg, backup_base_reg;
  rtx ffb_result;
  rtx target_char_ptr, length;
  rtx loop_label, tmp;

  if (optimize_size || optimize < 3)
    return false;

  gcc_assert (MEM_P (str));
  gcc_assert (CONST_INT_P (target_char) || REG_P (target_char));

  base_reg = copy_to_mode_reg (SImode, XEXP (str, 0));
  loop_label = gen_label_rtx ();

  ffb_result = gen_reg_rtx (Pmode);
  tmp = gen_reg_rtx (SImode);
  backup_base_reg = gen_reg_rtx (SImode);

  /* Emit loop version of strlen.
       move  $backup_base, $base
     .Lloop:
       lmw.bim $tmp, [$base], $tmp, 0
       ffb   $ffb_result, $tmp, $target_char   ! is there $target_char?
       beqz  $ffb_result, .Lloop
       add   $last_char_ptr, $base, $ffb_result
       sub   $length, $last_char_ptr, $backup_base  */

  /* move  $backup_base, $base  */
  emit_move_insn (backup_base_reg, base_reg);

  /* .Lloop:  */
  emit_label (loop_label);
  /* lmw.bim $tmp, [$base], $tmp, 0  */
  emit_insn (gen_unaligned_load_update_base_w (base_reg, tmp, base_reg));

  /*  ffb   $ffb_result, $tmp, $target_char   ! is there $target_char?  */
  emit_insn (gen_unspec_ffb (ffb_result, tmp, target_char));

  /* beqz  $ffb_result, .Lloop  */
  emit_cmp_and_jump_insns (ffb_result, const0_rtx, EQ, NULL,
			   SImode, 1, loop_label);

  /* add   $target_char_ptr, $base, $ffb_result   */
  target_char_ptr = expand_binop (Pmode, add_optab, base_reg,
				ffb_result, NULL_RTX, 0, OPTAB_WIDEN);

  /* sub   $length, $target_char_ptr, $backup_base  */
  length = expand_binop (Pmode, sub_optab, target_char_ptr,
			 backup_base_reg, NULL_RTX, 0, OPTAB_WIDEN);

  emit_move_insn (result, length);

  return true;
}
Пример #4
0
/* Generate code for transformations 3 and 4 (with MODE and OPERATION,
   operands OP1 and OP2, result TARGET, at most SUB subtractions, and
   probability of taking the optimal path(s) PROB1 and PROB2).  */
static rtx
gen_mod_subtract (enum machine_mode mode, enum rtx_code operation,
		  rtx target, rtx op1, rtx op2, int sub, int prob1, int prob2)
{
  rtx tmp, tmp1, jump;
  rtx end_label = gen_label_rtx ();
  rtx sequence;
  int i;

  start_sequence ();
  
  if (!REG_P (op2))
    {
      tmp = gen_reg_rtx (mode);
      emit_move_insn (tmp, copy_rtx (op2));
    }
  else
    tmp = op2;

  emit_move_insn (target, copy_rtx (op1));
  do_compare_rtx_and_jump (target, tmp, LTU, 0, mode, NULL_RTX,
			   NULL_RTX, end_label);

  /* Add branch probability to jump we just created.  */
  jump = get_last_insn ();
  REG_NOTES (jump) = gen_rtx_EXPR_LIST (REG_BR_PROB,
					GEN_INT (prob1), REG_NOTES (jump));

  for (i = 0; i < sub; i++)
    {
      tmp1 = expand_simple_binop (mode, MINUS, target, tmp, target,
	    			  0, OPTAB_WIDEN);
      if (tmp1 != target)
	emit_move_insn (target, tmp1);
      do_compare_rtx_and_jump (target, tmp, LTU, 0, mode, NULL_RTX,
    			       NULL_RTX, end_label);

      /* Add branch probability to jump we just created.  */
      jump = get_last_insn ();
      REG_NOTES (jump) = gen_rtx_EXPR_LIST (REG_BR_PROB,
					    GEN_INT (prob2), REG_NOTES (jump));
    }

  tmp1 = simplify_gen_binary (operation, mode, copy_rtx (target), copy_rtx (tmp));
  tmp1 = force_operand (tmp1, target);
  if (tmp1 != target)
    emit_move_insn (target, tmp1);
  
  emit_label (end_label);

  sequence = get_insns ();
  end_sequence ();
  rebuild_jump_labels (sequence);
  return sequence;
}
Пример #5
0
Файл: lm32.c Проект: boomeer/gcc
/* Generate and emit RTL to save or restore callee save registers.  */
static void
expand_save_restore (struct lm32_frame_info *info, int op)
{
  unsigned int reg_save_mask = info->reg_save_mask;
  int regno;
  HOST_WIDE_INT offset;
  rtx insn;

  /* Callee saves are below locals and above outgoing arguments.  */
  offset = info->args_size + info->callee_size;
  for (regno = 0; regno <= 31; regno++)
    {
      if ((reg_save_mask & (1 << regno)) != 0)
	{
	  rtx offset_rtx;
	  rtx mem;
	  
	  offset_rtx = GEN_INT (offset);
	  if (satisfies_constraint_K (offset_rtx))
	    {	
              mem = gen_rtx_MEM (word_mode,
                                 gen_rtx_PLUS (Pmode,
                                               stack_pointer_rtx,
                                               offset_rtx));
            }
          else
            {
              /* r10 is caller saved so it can be used as a temp reg.  */
              rtx r10;        
               
              r10 = gen_rtx_REG (word_mode, 10);
              insn = emit_move_insn (r10, offset_rtx);
              if (op == 0)
                RTX_FRAME_RELATED_P (insn) = 1;
              insn = emit_add (r10, r10, stack_pointer_rtx);
              if (op == 0)
                RTX_FRAME_RELATED_P (insn) = 1;                
              mem = gen_rtx_MEM (word_mode, r10);
            }                                                 	    
	    	    
	  if (op == 0)
	    insn = emit_move_insn (mem, gen_rtx_REG (word_mode, regno));
	  else
	    insn = emit_move_insn (gen_rtx_REG (word_mode, regno), mem);
        
	  /* only prologue instructions which set the sp fp or save a
	     register should be marked as frame related.  */
	  if (op == 0)
	    RTX_FRAME_RELATED_P (insn) = 1;
	  offset -= UNITS_PER_WORD;
	}
    }
}
Пример #6
0
static void
nds32_emit_load_store (rtx reg, rtx mem,
		       enum machine_mode mode,
		       int offset, bool load_p)
{
  rtx new_mem;
  new_mem = adjust_address (mem, mode, offset);
  if (load_p)
    emit_move_insn (reg, new_mem);
  else
    emit_move_insn (new_mem, reg);
}
Пример #7
0
/* Generate code for transformation 2 (with MODE and OPERATION, operands OP1
   and OP2, result TARGET and probability of taking the optimal path PROB).  */
static rtx
gen_mod_pow2 (enum machine_mode mode, enum rtx_code operation, rtx target,
	      rtx op1, rtx op2, int prob)
{
  rtx tmp, tmp1, tmp2, tmp3, jump;
  rtx neq_label = gen_label_rtx ();
  rtx end_label = gen_label_rtx ();
  rtx sequence;

  start_sequence ();
  
  if (!REG_P (op2))
    {
      tmp = gen_reg_rtx (mode);
      emit_move_insn (tmp, copy_rtx (op2));
    }
  else
    tmp = op2;

  tmp1 = expand_simple_binop (mode, PLUS, tmp, constm1_rtx, NULL_RTX,
			      0, OPTAB_WIDEN);
  tmp2 = expand_simple_binop (mode, AND, tmp, tmp1, NULL_RTX,
			      0, OPTAB_WIDEN);
  do_compare_rtx_and_jump (tmp2, const0_rtx, NE, 0, mode, NULL_RTX,
			   NULL_RTX, neq_label);

  /* Add branch probability to jump we just created.  */
  jump = get_last_insn ();
  REG_NOTES (jump) = gen_rtx_EXPR_LIST (REG_BR_PROB,
					GEN_INT (REG_BR_PROB_BASE - prob),
					REG_NOTES (jump));

  tmp3 = expand_simple_binop (mode, AND, op1, tmp1, target,
			      0, OPTAB_WIDEN);
  if (tmp3 != target)
    emit_move_insn (copy_rtx (target), tmp3);
  emit_jump_insn (gen_jump (end_label));
  emit_barrier ();

  emit_label (neq_label);
  tmp1 = simplify_gen_binary (operation, mode, copy_rtx (op1), copy_rtx (tmp));
  tmp1 = force_operand (tmp1, target);
  if (tmp1 != target)
    emit_move_insn (target, tmp1);
  
  emit_label (end_label);

  sequence = get_insns ();
  end_sequence ();
  rebuild_jump_labels (sequence);
  return sequence;
}
Пример #8
0
/* Generate code for transformation 1 (with MODE and OPERATION, operands OP1
   and OP2, whose value is expected to be VALUE, result TARGET and
   probability of taking the optimal path PROB).  */
static rtx
gen_divmod_fixed_value (enum machine_mode mode, enum rtx_code operation,
			rtx target, rtx op1, rtx op2, gcov_type value,
			int prob)
{
  rtx tmp, tmp1, jump;
  rtx neq_label = gen_label_rtx ();
  rtx end_label = gen_label_rtx ();
  rtx sequence;

  start_sequence ();
  
  if (!REG_P (op2))
    {
      tmp = gen_reg_rtx (mode);
      emit_move_insn (tmp, copy_rtx (op2));
    }
  else
    tmp = op2;

  do_compare_rtx_and_jump (tmp, GEN_INT (value), NE, 0, mode, NULL_RTX,
			   NULL_RTX, neq_label);

  /* Add branch probability to jump we just created.  */
  jump = get_last_insn ();
  REG_NOTES (jump) = gen_rtx_EXPR_LIST (REG_BR_PROB,
					GEN_INT (REG_BR_PROB_BASE - prob),
					REG_NOTES (jump));

  tmp1 = simplify_gen_binary (operation, mode,
			      copy_rtx (op1), GEN_INT (value));
  tmp1 = force_operand (tmp1, target);
  if (tmp1 != target)
    emit_move_insn (copy_rtx (target), copy_rtx (tmp1));

  emit_jump_insn (gen_jump (end_label));
  emit_barrier ();

  emit_label (neq_label);
  tmp1 = simplify_gen_binary (operation, mode,
			      copy_rtx (op1), copy_rtx (tmp));
  tmp1 = force_operand (tmp1, target);
  if (tmp1 != target)
    emit_move_insn (copy_rtx (target), copy_rtx (tmp1));
  
  emit_label (end_label);

  sequence = get_insns ();
  end_sequence ();
  rebuild_jump_labels (sequence);
  return sequence;
}
Пример #9
0
static void
moxie_trampoline_init (rtx m_tramp, tree fndecl, rtx chain_value)
{
  rtx mem, fnaddr = XEXP (DECL_RTL (fndecl), 0);

  emit_block_move (m_tramp, assemble_trampoline_template (),
		   GEN_INT (TRAMPOLINE_SIZE), BLOCK_OP_NORMAL);

  mem = adjust_address (m_tramp, SImode, 4);
  emit_move_insn (mem, chain_value);
  mem = adjust_address (m_tramp, SImode, 16);
  emit_move_insn (mem, fnaddr);
}
Пример #10
0
static void
lm32_block_move_inline (rtx dest, rtx src, HOST_WIDE_INT length, HOST_WIDE_INT alignment)
{
    HOST_WIDE_INT offset, delta;
    unsigned HOST_WIDE_INT bits;
    int i;
    enum machine_mode mode;
    rtx *regs;

    /* Work out how many bits to move at a time.  */
    switch (alignment)
    {
    case 1:
        bits = 8;
        break;
    case 2:
        bits = 16;
        break;
    case 4:
        bits = 32;
        break;
    default:
        abort ();
    }

    mode = mode_for_size (bits, MODE_INT, 0);
    delta = bits / BITS_PER_UNIT;

    /* Allocate a buffer for the temporary registers.  */
    regs = alloca (sizeof (rtx) * length / delta);

    /* Load as many BITS-sized chunks as possible.  */
    for (offset = 0, i = 0; offset + delta <= length; offset += delta, i++)
    {
        regs[i] = gen_reg_rtx (mode);
        emit_move_insn (regs[i], adjust_address (src, mode, offset));
    }

    /* Copy the chunks to the destination.  */
    for (offset = 0, i = 0; offset + delta <= length; offset += delta, i++)
        emit_move_insn (adjust_address (dest, mode, offset), regs[i]);

    /* Mop up any left-over bytes.  */
    if (offset < length)
    {
        src = adjust_address (src, BLKmode, offset);
        dest = adjust_address (dest, BLKmode, offset);
        move_by_pieces (dest, src, length - offset,
                        MIN (MEM_ALIGN (src), MEM_ALIGN (dest)), 0);
    }
}
Пример #11
0
Файл: lm32.c Проект: boomeer/gcc
static void
stack_adjust (HOST_WIDE_INT amount)
{
  rtx insn;

  if (!IN_RANGE (amount, -32776, 32768))
    {
      /* r10 is caller saved so it can be used as a temp reg.  */
      rtx r10;
      r10 = gen_rtx_REG (word_mode, 10);
      insn = emit_move_insn (r10, GEN_INT (amount));
      if (amount < 0)
	RTX_FRAME_RELATED_P (insn) = 1;
      insn = emit_add (stack_pointer_rtx, stack_pointer_rtx, r10);
      if (amount < 0)
	RTX_FRAME_RELATED_P (insn) = 1;
    }
  else
    {
      insn = emit_add (stack_pointer_rtx,
		       stack_pointer_rtx, GEN_INT (amount));
      if (amount < 0)
	RTX_FRAME_RELATED_P (insn) = 1;
    }
}
void
crx_expand_epilogue (void)
{
  rtx return_reg;

  /* Nonzero if we need to return and pop only RA. This will generate a
   * different insn. This differentiate is for the peepholes for call as last
   * statement in function. */
  int only_popret_RA = (save_regs[RETURN_ADDRESS_REGNUM]
			&& (sum_regs == UNITS_PER_WORD));

  /* Return register.  */
  return_reg = gen_rtx_REG (Pmode, RETURN_ADDRESS_REGNUM);

  if (frame_pointer_needed)
    /* Restore the stack pointer with the frame pointers value */
    emit_move_insn (stack_pointer_rtx, frame_pointer_rtx);

  if (size_for_adjusting_sp > 0)
    emit_insn (gen_addsi3 (stack_pointer_rtx, stack_pointer_rtx,
			   GEN_INT (size_for_adjusting_sp)));

  if (crx_interrupt_function_p ())
    emit_jump_insn (gen_interrupt_return ());
  else if (last_reg_to_save == -1)
    /* Nothing to pop */
    /* Don't output jump for interrupt routine, only retx.  */
    emit_jump_insn (gen_indirect_jump_return ());
  else if (only_popret_RA)
    emit_jump_insn (gen_popret_RA_return ());
  else
    emit_jump_insn (gen_pop_and_popret_return (GEN_INT (sum_regs)));
}
Пример #13
0
static void
moxie_setup_incoming_varargs (cumulative_args_t cum_v,
			      machine_mode mode ATTRIBUTE_UNUSED,
			      tree type ATTRIBUTE_UNUSED,
			      int *pretend_size, int no_rtl)
{
  CUMULATIVE_ARGS *cum = get_cumulative_args (cum_v);
  int regno;
  int regs = 8 - *cum;
  
  *pretend_size = regs < 0 ? 0 : GET_MODE_SIZE (SImode) * regs;
  
  if (no_rtl)
    return;
  
  for (regno = *cum; regno < 8; regno++)
    {
      rtx reg = gen_rtx_REG (SImode, regno);
      rtx slot = gen_rtx_PLUS (Pmode,
			       gen_rtx_REG (SImode, ARG_POINTER_REGNUM),
			       GEN_INT (UNITS_PER_WORD * (3 + (regno-2))));
      
      emit_move_insn (gen_rtx_MEM (SImode, slot), reg);
    }
}
Пример #14
0
static rtx
emit_setmem_doubleword_loop (rtx itr, rtx size, rtx value)
{
  rtx word_mode_label = gen_label_rtx ();
  rtx word_mode_end_label = gen_label_rtx ();
  rtx byte_mode_size = gen_reg_rtx (SImode);
  rtx byte_mode_size_tmp = gen_reg_rtx (SImode);
  rtx word_mode_end = gen_reg_rtx (SImode);
  rtx size_for_word = gen_reg_rtx (SImode);

  /* and     $size_for_word, $size, #~0x7  */
  size_for_word = expand_binop (SImode, and_optab, size,
				gen_int_mode (~0x7, SImode),
				NULL_RTX, 0, OPTAB_WIDEN);

  emit_move_insn (byte_mode_size, size);

  /* beqz    $size_for_word, .Lbyte_mode_entry  */
  emit_cmp_and_jump_insns (size_for_word, const0_rtx, EQ, NULL,
			   SImode, 1, word_mode_end_label);
  /* add     $word_mode_end, $dst, $size_for_word  */
  word_mode_end = expand_binop (Pmode, add_optab, itr, size_for_word,
				NULL_RTX, 0, OPTAB_WIDEN);

  /* andi    $byte_mode_size, $size, 0x7  */
  byte_mode_size_tmp = expand_binop (SImode, and_optab, size, GEN_INT (0x7),
				     NULL_RTX, 0, OPTAB_WIDEN);

  emit_move_insn (byte_mode_size, byte_mode_size_tmp);

  /* .Lword_mode:  */
  emit_label (word_mode_label);
  /*   ! word-mode set loop
       smw.bim $value4word, [$dst_itr], $value4word, 0
       bne     $word_mode_end, $dst_itr, .Lword_mode  */
  emit_insn (gen_unaligned_store_update_base_dw (itr,
						 itr,
						 value));
  emit_cmp_and_jump_insns (word_mode_end, itr, NE, NULL,
			   Pmode, 1, word_mode_label);

  emit_label (word_mode_end_label);

  return byte_mode_size;
}
Пример #15
0
static rtx
nds32_gen_dup_4_byte_to_word_value_aux (rtx value, rtx value4word)
{
  gcc_assert (GET_MODE (value) == QImode || CONST_INT_P (value));

  if (CONST_INT_P (value))
    {
      unsigned HOST_WIDE_INT val = UINTVAL (value) & GET_MODE_MASK(QImode);
      rtx new_val = gen_int_mode (val | (val << 8)
				  | (val << 16) | (val << 24), SImode);
      /* Just calculate at here if it's constant value.  */
      emit_move_insn (value4word, new_val);
    }
  else
    {
      if (NDS32_EXT_DSP_P ())
	{
	  /* ! prepare word
	     insb    $tmp, $value, 1         ! $tmp  <- 0x0000abab
	     pkbb16  $tmp6, $tmp2, $tmp2   ! $value4word  <- 0xabababab */
	  rtx tmp = gen_reg_rtx (SImode);

	  convert_move (tmp, value, true);

	  emit_insn (
	    gen_insvsi_internal (tmp, gen_int_mode (0x8, SImode), tmp));

	  emit_insn (gen_pkbbsi_1 (value4word, tmp, tmp));
	}
      else
	{
	  /* ! prepare word
	     andi    $tmp1, $value, 0xff       ! $tmp1  <- 0x000000ab
	     slli    $tmp2, $tmp1, 8           ! $tmp2  <- 0x0000ab00
	     or      $tmp3, $tmp1, $tmp2       ! $tmp3  <- 0x0000abab
	     slli    $tmp4, $tmp3, 16          ! $tmp4  <- 0xabab0000
	     or      $val4word, $tmp3, $tmp4   ! $value4word  <- 0xabababab  */

	  rtx tmp1, tmp2, tmp3, tmp4;
	  tmp1 = expand_binop (SImode, and_optab, value,
			       gen_int_mode (0xff, SImode),
			       NULL_RTX, 0, OPTAB_WIDEN);
	  tmp2 = expand_binop (SImode, ashl_optab, tmp1,
			       gen_int_mode (8, SImode),
			       NULL_RTX, 0, OPTAB_WIDEN);
	  tmp3 = expand_binop (SImode, ior_optab, tmp1, tmp2,
			       NULL_RTX, 0, OPTAB_WIDEN);
	  tmp4 = expand_binop (SImode, ashl_optab, tmp3,
			       gen_int_mode (16, SImode),
			       NULL_RTX, 0, OPTAB_WIDEN);

	  emit_insn (gen_iorsi3 (value4word, tmp3, tmp4));
	}
    }

  return value4word;
}
void crx_expand_movmem_single (rtx src, rtx srcbase, rtx dst, rtx dstbase,
			       rtx tmp_reg, unsigned HOST_WIDE_INT *offset_p)
{
  rtx addr, mem;
  unsigned HOST_WIDE_INT offset = *offset_p;

  /* Load */
  addr = plus_constant (src, offset);
  mem = adjust_automodify_address (srcbase, SImode, addr, offset);
  emit_move_insn (tmp_reg, mem);

  /* Store */
  addr = plus_constant (dst, offset);
  mem = adjust_automodify_address (dstbase, SImode, addr, offset);
  emit_move_insn (mem, tmp_reg);

  *offset_p = offset + 4;
}
Пример #17
0
static void
insert_value_copy_on_edge (edge e, int dest, tree src, source_location locus)
{
  rtx seq, x;
  enum machine_mode dest_mode, src_mode;
  int unsignedp;
  tree var;

  if (dump_file && (dump_flags & TDF_DETAILS))
    {
      fprintf (dump_file,
	       "Inserting a value copy on edge BB%d->BB%d : PART.%d = ",
	       e->src->index,
	       e->dest->index, dest);
      print_generic_expr (dump_file, src, TDF_SLIM);
      fprintf (dump_file, "\n");
    }

  gcc_assert (SA.partition_to_pseudo[dest]);

  set_location_for_edge (e);
  /* If a locus is provided, override the default.  */
  if (locus)
    set_curr_insn_source_location (locus);

  start_sequence ();

  var = SSA_NAME_VAR (partition_to_var (SA.map, dest));
  src_mode = TYPE_MODE (TREE_TYPE (src));
  dest_mode = GET_MODE (SA.partition_to_pseudo[dest]);
  gcc_assert (src_mode == TYPE_MODE (TREE_TYPE (var)));
  gcc_assert (!REG_P (SA.partition_to_pseudo[dest])
	      || dest_mode == promote_decl_mode (var, &unsignedp));

  if (src_mode != dest_mode)
    {
      x = expand_expr (src, NULL, src_mode, EXPAND_NORMAL);
      x = convert_modes (dest_mode, src_mode, x, unsignedp);
    }
  else if (src_mode == BLKmode)
    {
      x = SA.partition_to_pseudo[dest];
      store_expr (src, x, 0, false);
    }
  else
    x = expand_expr (src, SA.partition_to_pseudo[dest],
		     dest_mode, EXPAND_NORMAL);

  if (x != SA.partition_to_pseudo[dest])
    emit_move_insn (SA.partition_to_pseudo[dest], x);
  seq = get_insns ();
  end_sequence ();

  insert_insn_on_edge (seq, e);
}
Пример #18
0
static rtx
nds32_gen_dup_8_byte_to_double_word_value (rtx value)
{
  rtx value4doubleword = gen_reg_rtx (DImode);

  nds32_gen_dup_4_byte_to_word_value_aux (
    value, nds32_di_low_part_subreg(value4doubleword));

  emit_move_insn (nds32_di_high_part_subreg(value4doubleword),
		  nds32_di_low_part_subreg(value4doubleword));
  return value4doubleword;
}
Пример #19
0
static rtx
insert_move_insn_before (rtx next_insn, rtx dest_reg, rtx src_reg)
{
  rtx insns;

  start_sequence ();
  emit_move_insn (dest_reg, src_reg);
  insns = get_insns ();
  end_sequence ();
  emit_insn_before (insns, next_insn);
  return insns;
}
Пример #20
0
static void
nds32_emit_post_inc_load_store (rtx reg, rtx base_reg,
				enum machine_mode mode,
				bool load_p)
{
  gcc_assert (GET_MODE (reg) == mode);
  gcc_assert (GET_MODE (base_reg) == Pmode);

  /* Do not gen (set (reg) (mem (post_inc (reg)))) directly here since it may
     not recognize by gcc, so let gcc combine it at auto_inc_dec pass.  */
  if (load_p)
    emit_move_insn (reg,
		    gen_rtx_MEM (mode,
				 base_reg));
  else
    emit_move_insn (gen_rtx_MEM (mode,
				 base_reg),
		    reg);

  emit_move_insn (base_reg,
		  plus_constant(Pmode, base_reg, GET_MODE_SIZE (mode)));
}
Пример #21
0
/* Generate and emit RTL to save or restore callee save registers */
static void
expand_save_restore (struct lm32_frame_info *info, int op)
{
    unsigned int reg_save_mask = info->reg_save_mask;
    int regno;
    HOST_WIDE_INT offset;
    rtx insn;

    /* Callee saves are below locals and above outgoing arguments */
    offset = info->args_size + info->callee_size;
    for (regno = 0; regno <= 31; regno++)
    {
        if ((reg_save_mask & (1 << regno)) != 0)
        {
            if (op == 0)
            {
                insn = emit_move_insn (gen_rtx_MEM (word_mode,
                                                    gen_rtx_PLUS (Pmode,
                                                            stack_pointer_rtx,
                                                            GEN_INT (offset))),
                                       gen_rtx_REG (word_mode, regno));
            }
            else
            {
                insn = emit_move_insn (gen_rtx_REG (word_mode, regno),
                                       gen_rtx_MEM (word_mode,
                                                    gen_rtx_PLUS (Pmode,
                                                            stack_pointer_rtx,
                                                            GEN_INT (offset))));
            }

            /* only prologue instructions which set the sp fp or save a
               register should be marked as frame related */
            if (op==0)
                RTX_FRAME_RELATED_P (insn) = 1;
            offset -= UNITS_PER_WORD;
        }
    }
}
Пример #22
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;
	}
    }
}
Пример #23
0
static void
expand_BUILTIN_EXPECT (gimple stmt)
{
  /* When guessing was done, the hints should be already stripped away.  */
  gcc_assert (!flag_guess_branch_prob || optimize == 0 || seen_error ());

  rtx target;
  tree lhs = gimple_call_lhs (stmt);
  if (lhs)
    target = expand_expr (lhs, NULL_RTX, VOIDmode, EXPAND_WRITE);
  else
    target = const0_rtx;
  rtx val = expand_expr (gimple_call_arg (stmt, 0), target, VOIDmode, EXPAND_NORMAL);
  if (lhs && val != target)
    emit_move_insn (target, val);
}
Пример #24
0
static void
do_jump_by_parts_zero_rtx (enum machine_mode mode, rtx op0,
                           rtx if_false_label, rtx if_true_label)
{
  int nwords = GET_MODE_SIZE (mode) / UNITS_PER_WORD;
  rtx part;
  int i;
  rtx drop_through_label = 0;

  /* The fastest way of doing this comparison on almost any machine is to
     "or" all the words and compare the result.  If all have to be loaded
     from memory and this is a very wide item, it's possible this may
     be slower, but that's highly unlikely.  */

  part = gen_reg_rtx (word_mode);
  emit_move_insn (part, operand_subword_force (op0, 0, GET_MODE (op0)));
  for (i = 1; i < nwords && part != 0; i++)
    part = expand_binop (word_mode, ior_optab, part,
                         operand_subword_force (op0, i, GET_MODE (op0)),
                         part, 1, OPTAB_WIDEN);

  if (part != 0)
    {
      do_compare_rtx_and_jump (part, const0_rtx, EQ, 1, word_mode,
                               NULL_RTX, if_false_label, if_true_label);

      return;
    }

  /* If we couldn't do the "or" simply, do this with a series of compares.  */
  if (! if_false_label)
    drop_through_label = if_false_label = gen_label_rtx ();

  for (i = 0; i < nwords; i++)
    do_compare_rtx_and_jump (operand_subword_force (op0, i, GET_MODE (op0)),
                             const0_rtx, EQ, 1, word_mode, NULL_RTX,
                             if_false_label, NULL_RTX);

  if (if_true_label)
    emit_jump (if_true_label);

  if (drop_through_label)
    emit_label (drop_through_label);
}
Пример #25
0
void
c54x_expand_prologue()
{
	int r;

	for(r = 0; r < FIRST_PSEUDO_REGISTER; r++) {
		if(c54x_save_register_p(r)) {
			emit_insn(gen_pushqi(gen_rtx_REG(QImode, r)));
		}
	}

	if(frame_pointer_needed) {
		emit_move_insn(gen_rtx_REG (QImode,	FRAME_POINTER_REGNUM),
					   gen_rtx_REG (QImode, STACK_POINTER_REGNUM));
	}

	emit_insn(gen_frame(gen_rtx_REG (QImode, STACK_POINTER_REGNUM),
						gen_rtx_CONST_INT(VOIDmode, get_frame_size())));
}
Пример #26
0
unsigned int
emit_initial_value_sets (void)
{
  struct initial_value_struct *ivs = crtl->hard_reg_initial_vals;
  int i;
  rtx seq;

  if (ivs == 0)
    return 0;

  start_sequence ();
  for (i = 0; i < ivs->num_entries; i++)
    emit_move_insn (ivs->entries[i].pseudo, ivs->entries[i].hard_reg);
  seq = get_insns ();
  end_sequence ();

  emit_insn_at_entry (seq);
  return 0;
}
Пример #27
0
static inline rtx
emit_partition_copy (rtx dest, rtx src, int unsignedsrcp, tree sizeexp)
{
  rtx seq;

  start_sequence ();

  if (GET_MODE (src) != VOIDmode && GET_MODE (src) != GET_MODE (dest))
    src = convert_to_mode (GET_MODE (dest), src, unsignedsrcp);
  if (GET_MODE (src) == BLKmode)
    {
      gcc_assert (GET_MODE (dest) == BLKmode);
      emit_block_move (dest, src, expr_size (sizeexp), BLOCK_OP_NORMAL);
    }
  else
    emit_move_insn (dest, src);

  seq = get_insns ();
  end_sequence ();

  return seq;
}
void
crx_expand_prologue (void)
{
  crx_compute_frame ();
  crx_compute_save_regs ();

  /* If there is no need in push and adjustment to sp, return. */
  if (size_for_adjusting_sp + sum_regs == 0)
    return;

  if (last_reg_to_save != -1)
    /* If there are registers to push.  */
    emit_insn (gen_push_for_prologue (GEN_INT (sum_regs)));

  if (size_for_adjusting_sp > 0)
    emit_insn (gen_addsi3 (stack_pointer_rtx, stack_pointer_rtx,
			   GEN_INT (-size_for_adjusting_sp)));

  if (frame_pointer_needed)
    /* Initialize the frame pointer with the value of the stack pointer
     * pointing now to the locals. */
    emit_move_insn (frame_pointer_rtx, stack_pointer_rtx);
}
Пример #29
0
Файл: lm32.c Проект: boomeer/gcc
/* Create and emit instructions for a functions prologue.  */
void
lm32_expand_prologue (void)
{
  rtx insn;

  lm32_compute_frame_size (get_frame_size ());

  if (current_frame_info.total_size > 0)
    {
      /* Add space on stack new frame.  */
      stack_adjust (-current_frame_info.total_size);

      /* Save callee save registers.  */
      if (current_frame_info.reg_save_mask != 0)
	expand_save_restore (&current_frame_info, 0);

      /* Setup frame pointer if it's needed.  */
      if (frame_pointer_needed == 1)
	{
	  /* Move sp to fp.  */
	  insn = emit_move_insn (frame_pointer_rtx, stack_pointer_rtx);
	  RTX_FRAME_RELATED_P (insn) = 1; 

	  /* Add offset - Don't use total_size, as that includes pretend_size, 
             which isn't part of this frame?  */
	  insn = emit_add (frame_pointer_rtx, 
			   frame_pointer_rtx,
			   GEN_INT (current_frame_info.args_size +
				    current_frame_info.callee_size +
				    current_frame_info.locals_size));
	  RTX_FRAME_RELATED_P (insn) = 1;
	}

      /* Prevent prologue from being scheduled into function body.  */
      emit_insn (gen_blockage ());
    }
}
Пример #30
0
Файл: lm32.c Проект: boomeer/gcc
static void
gen_int_relational (enum rtx_code code,	
		    rtx result,	
		    rtx cmp0,	
		    rtx cmp1,	
		    rtx destination)	
{
  machine_mode mode;
  int branch_p;

  mode = GET_MODE (cmp0);
  if (mode == VOIDmode)
    mode = GET_MODE (cmp1);

  /* Is this a branch or compare.  */
  branch_p = (destination != 0);

  /* Instruction set doesn't support LE or LT, so swap operands and use 
     GE, GT.  */
  switch (code)
    {
    case LE:
    case LT:
    case LEU:
    case LTU:
      {
	rtx temp;

	code = swap_condition (code);
	temp = cmp0;
	cmp0 = cmp1;
	cmp1 = temp;
	break;
      }
    default:
      break;
    }

  if (branch_p)
    {
      rtx insn, cond, label;

      /* Operands must be in registers.  */
      if (!register_operand (cmp0, mode))
	cmp0 = force_reg (mode, cmp0);
      if (!register_operand (cmp1, mode))
	cmp1 = force_reg (mode, cmp1);

      /* Generate conditional branch instruction.  */
      cond = gen_rtx_fmt_ee (code, mode, cmp0, cmp1);
      label = gen_rtx_LABEL_REF (VOIDmode, destination);
      insn = gen_rtx_SET (pc_rtx, gen_rtx_IF_THEN_ELSE (VOIDmode,
							cond, label, pc_rtx));
      emit_jump_insn (insn);
    }
  else
    {
      /* We can't have const_ints in cmp0, other than 0.  */
      if ((GET_CODE (cmp0) == CONST_INT) && (INTVAL (cmp0) != 0))
	cmp0 = force_reg (mode, cmp0);

      /* If the comparison is against an int not in legal range
         move it into a register.  */
      if (GET_CODE (cmp1) == CONST_INT)
	{
	  switch (code)
	    {
	    case EQ:
	    case NE:
	    case LE:
	    case LT:
	    case GE:
	    case GT:
	      if (!satisfies_constraint_K (cmp1))
		cmp1 = force_reg (mode, cmp1);
	      break;
	    case LEU:
	    case LTU:
	    case GEU:
	    case GTU:
	      if (!satisfies_constraint_L (cmp1))
		cmp1 = force_reg (mode, cmp1);
	      break;
	    default:
	      gcc_unreachable ();
	    }
	}

      /* Generate compare instruction.  */
      emit_move_insn (result, gen_rtx_fmt_ee (code, mode, cmp0, cmp1));
    }
}