コード例 #1
0
ファイル: nds32-predicates.c プロジェクト: asutton/gcc
/* Vaild memory operand for floating-point loads and stores */
bool
nds32_float_mem_operand_p (rtx op)
{
  machine_mode mode = GET_MODE (op);
  rtx addr = XEXP (op, 0);

  /* Not support [symbol] [const] memory */
  if (GET_CODE (addr) == SYMBOL_REF
      || GET_CODE (addr) == CONST
      || GET_CODE (addr) == LO_SUM)
    return false;

  if (GET_CODE (addr) == PLUS)
    {
      if (GET_CODE (XEXP (addr, 0)) == SYMBOL_REF)
	return false;

      /* Restrict const range: (imm12s << 2) */
      if (GET_CODE (XEXP (addr, 1)) == CONST_INT)
	{
	  if ((mode == SImode || mode == SFmode)
	      && NDS32_SINGLE_WORD_ALIGN_P (INTVAL (XEXP (addr, 1)))
	      && !satisfies_constraint_Is14 ( XEXP(addr, 1)))
	    return false;

	  if ((mode == DImode || mode == DFmode)
	      && NDS32_DOUBLE_WORD_ALIGN_P (INTVAL (XEXP (addr, 1)))
	      && !satisfies_constraint_Is14 (XEXP (addr, 1)))
	    return false;
	}
    }

  return true;
}
コード例 #2
0
ファイル: nds32-md-auxiliary.c プロジェクト: alcides/gcc
/* Function to output stack pop operation.
   We need to deal with normal stack pop multiple or stack v3pop.  */
const char *
nds32_output_stack_pop (rtx par_rtx ATTRIBUTE_UNUSED)
{
  /* A string pattern for output_asm_insn().  */
  char pattern[100];
  /* The operands array which will be used in output_asm_insn().  */
  rtx operands[3];
  /* Pick up callee-saved first regno and last regno for further use.  */
  int rb_callee_saved = cfun->machine->callee_saved_regs_first_regno;
  int re_callee_saved = cfun->machine->callee_saved_regs_last_regno;

  /* If we step here, we are going to do v3pop or multiple pop operation.  */

  /* The v3push/v3pop instruction should only be applied on
     none-isr and none-variadic function.  */
  if (TARGET_V3PUSH
      && !nds32_isr_function_p (current_function_decl)
      && (cfun->machine->va_args_size == 0))
    {
      /* For stack v3pop:
           operands[0]: Re
           operands[1]: imm8u */

      /* This variable is to check if 'pop25 Re,imm8u' is available.  */
      int sp_adjust;

      /* Set operands[0].  */
      operands[0] = gen_rtx_REG (SImode, re_callee_saved);

      /* Check if we can generate 'pop25 Re,imm8u',
         otherwise, generate 'pop25 Re,0'.
         We have to consider alloca issue as well.
         If the function does call alloca(), the stack pointer is not fixed.
         In that case, we cannot use 'pop25 Re,imm8u' directly.
         We have to caculate stack pointer from frame pointer
         and then use 'pop25 Re,0'.  */
      sp_adjust = cfun->machine->local_size
		  + cfun->machine->out_args_size
		  + cfun->machine->callee_saved_area_padding_bytes;
      if (satisfies_constraint_Iu08 (GEN_INT (sp_adjust))
	  && NDS32_DOUBLE_WORD_ALIGN_P (sp_adjust)
	  && !cfun->calls_alloca)
	operands[1] = GEN_INT (sp_adjust);
      else
	operands[1] = GEN_INT (0);

      /* Create assembly code pattern.  */
      snprintf (pattern, sizeof (pattern), "pop25\t%%0, %%1");
    }
  else
    {
      /* For normal stack pop multiple:
         operands[0]: Rb
         operands[1]: Re
         operands[2]: En4 */

      /* This variable is used to check if we only need to generate En4 field.
         As long as Rb==Re=SP_REGNUM, we set this variable to 1.  */
      int pop_en4_only_p = 0;

      /* Set operands[0] and operands[1].  */
      operands[0] = gen_rtx_REG (SImode, rb_callee_saved);
      operands[1] = gen_rtx_REG (SImode, re_callee_saved);

      /* 'lmw.bim $sp,[$sp],$sp,0' means pop nothing.  */
      if (!cfun->machine->fp_size
	  && !cfun->machine->gp_size
	  && !cfun->machine->lp_size
	  && REGNO (operands[0]) == SP_REGNUM
	  && REGNO (operands[1]) == SP_REGNUM)
	{
	  /* No need to generate instruction.  */
	  return "";
	}
      else
	{
	  /* If Rb==Re=SP_REGNUM, we only need to generate En4 field.  */
	  if (REGNO (operands[0]) == SP_REGNUM
	      && REGNO (operands[1]) == SP_REGNUM)
	    pop_en4_only_p = 1;

	  /* Create assembly code pattern.
	     We need to handle the form: "Rb, Re, { $fp $gp $lp }".  */
	  snprintf (pattern, sizeof (pattern),
		    "pop.s\t%s{%s%s%s }",
		    pop_en4_only_p ? "" : "%0, %1, ",
		    cfun->machine->fp_size ? " $fp" : "",
		    cfun->machine->gp_size ? " $gp" : "",
		    cfun->machine->lp_size ? " $lp" : "");
	}
    }

  /* We use output_asm_insn() to output assembly code by ourself.  */
  output_asm_insn (pattern, operands);
  return "";
}
コード例 #3
0
ファイル: nds32-md-auxiliary.c プロジェクト: alcides/gcc
/* Function to output stack push operation.
   We need to deal with normal stack push multiple or stack v3push.  */
const char *
nds32_output_stack_push (rtx par_rtx)
{
  /* A string pattern for output_asm_insn().  */
  char pattern[100];
  /* The operands array which will be used in output_asm_insn().  */
  rtx operands[3];
  /* Pick up varargs first regno and last regno for further use.  */
  int rb_va_args = cfun->machine->va_args_first_regno;
  int re_va_args = cfun->machine->va_args_last_regno;
  int last_argument_regno = NDS32_FIRST_GPR_REGNUM
			    + NDS32_MAX_GPR_REGS_FOR_ARGS
			    - 1;
  /* Pick up callee-saved first regno and last regno for further use.  */
  int rb_callee_saved = cfun->machine->callee_saved_regs_first_regno;
  int re_callee_saved = cfun->machine->callee_saved_regs_last_regno;

  /* First we need to check if we are pushing argument registers not used
     for the named arguments.  If so, we have to create 'smw.adm' (push.s)
     instruction.  */
  if (reg_mentioned_p (gen_rtx_REG (SImode, last_argument_regno), par_rtx))
    {
      /* Set operands[0] and operands[1].  */
      operands[0] = gen_rtx_REG (SImode, rb_va_args);
      operands[1] = gen_rtx_REG (SImode, re_va_args);
      /* Create assembly code pattern: "Rb, Re, { }".  */
      snprintf (pattern, sizeof (pattern), "push.s\t%s", "%0, %1, { }");
      /* We use output_asm_insn() to output assembly code by ourself.  */
      output_asm_insn (pattern, operands);
      return "";
    }

  /* If we step here, we are going to do v3push or multiple push operation.  */

  /* The v3push/v3pop instruction should only be applied on
     none-isr and none-variadic function.  */
  if (TARGET_V3PUSH
      && !nds32_isr_function_p (current_function_decl)
      && (cfun->machine->va_args_size == 0))
    {
      /* For stack v3push:
           operands[0]: Re
           operands[1]: imm8u */

      /* This variable is to check if 'push25 Re,imm8u' is available.  */
      int sp_adjust;

      /* Set operands[0].  */
      operands[0] = gen_rtx_REG (SImode, re_callee_saved);

      /* Check if we can generate 'push25 Re,imm8u',
         otherwise, generate 'push25 Re,0'.  */
      sp_adjust = cfun->machine->local_size
		  + cfun->machine->out_args_size
		  + cfun->machine->callee_saved_area_padding_bytes;
      if (satisfies_constraint_Iu08 (GEN_INT (sp_adjust))
	  && NDS32_DOUBLE_WORD_ALIGN_P (sp_adjust))
	operands[1] = GEN_INT (sp_adjust);
      else
	operands[1] = GEN_INT (0);

      /* Create assembly code pattern.  */
      snprintf (pattern, sizeof (pattern), "push25\t%%0, %%1");
    }
  else
    {
      /* For normal stack push multiple:
         operands[0]: Rb
         operands[1]: Re
         operands[2]: En4 */

      /* This variable is used to check if we only need to generate En4 field.
         As long as Rb==Re=SP_REGNUM, we set this variable to 1.  */
      int push_en4_only_p = 0;

      /* Set operands[0] and operands[1].  */
      operands[0] = gen_rtx_REG (SImode, rb_callee_saved);
      operands[1] = gen_rtx_REG (SImode, re_callee_saved);

      /* 'smw.adm $sp,[$sp],$sp,0' means push nothing.  */
      if (!cfun->machine->fp_size
	  && !cfun->machine->gp_size
	  && !cfun->machine->lp_size
	  && REGNO (operands[0]) == SP_REGNUM
	  && REGNO (operands[1]) == SP_REGNUM)
	{
	  /* No need to generate instruction.  */
	  return "";
	}
      else
	{
	  /* If Rb==Re=SP_REGNUM, we only need to generate En4 field.  */
	  if (REGNO (operands[0]) == SP_REGNUM
	      && REGNO (operands[1]) == SP_REGNUM)
	    push_en4_only_p = 1;

	  /* Create assembly code pattern.
	     We need to handle the form: "Rb, Re, { $fp $gp $lp }".  */
	  snprintf (pattern, sizeof (pattern),
		    "push.s\t%s{%s%s%s }",
		    push_en4_only_p ? "" : "%0, %1, ",
		    cfun->machine->fp_size ? " $fp" : "",
		    cfun->machine->gp_size ? " $gp" : "",
		    cfun->machine->lp_size ? " $lp" : "");
	}
    }

  /* We use output_asm_insn() to output assembly code by ourself.  */
  output_asm_insn (pattern, operands);
  return "";
}