⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 arm.c

📁 linux下的gcc编译器
💻 C
📖 第 1 页 / 共 5 页
字号:
      && TREE_THIS_VOLATILE (current_function_decl))    type |= ARM_FT_VOLATILE;    if (current_function_needs_context)    type |= ARM_FT_NESTED;  attr = DECL_ATTRIBUTES (current_function_decl);    a = lookup_attribute ("naked", attr);  if (a != NULL_TREE)    type |= ARM_FT_NAKED;  if (cfun->machine->eh_epilogue_sp_ofs != NULL_RTX)    type |= ARM_FT_EXCEPTION_HANDLER;  else    {      a = lookup_attribute ("isr", attr);      if (a == NULL_TREE)	a = lookup_attribute ("interrupt", attr);            if (a == NULL_TREE)	type |= TARGET_INTERWORK ? ARM_FT_INTERWORKED : ARM_FT_NORMAL;      else	type |= arm_isr_value (TREE_VALUE (a));    }    return type;}/* Returns the type of the current function.  */unsigned longarm_current_func_type (){  if (ARM_FUNC_TYPE (cfun->machine->func_type) == ARM_FT_UNKNOWN)    cfun->machine->func_type = arm_compute_func_type ();  return cfun->machine->func_type;}/* Return 1 if it is possible to return using a single instruction.  */intuse_return_insn (iscond)     int iscond;{  int regno;  unsigned int func_type;  unsigned long saved_int_regs;  /* Never use a return instruction before reload has run.  */  if (!reload_completed)    return 0;        func_type = arm_current_func_type ();  /* Naked functions and volatile functions need special     consideration.  */  if (func_type & (ARM_FT_VOLATILE | ARM_FT_NAKED))    return 0;  /* So do interrupt functions that use the frame pointer.  */  if (IS_INTERRUPT (func_type) && frame_pointer_needed)    return 0;    /* As do variadic functions.  */  if (current_function_pretend_args_size      || cfun->machine->uses_anonymous_args      /* Of if the function calls __builtin_eh_return () */      || ARM_FUNC_TYPE (func_type) == ARM_FT_EXCEPTION_HANDLER      /* Or if there is no frame pointer and there is a stack adjustment.  */      || ((arm_get_frame_size () + current_function_outgoing_args_size != 0)	  && !frame_pointer_needed))    return 0;  saved_int_regs = arm_compute_save_reg_mask ();  /* Can't be done if interworking with Thumb, and any registers have been     stacked.  */  if (TARGET_INTERWORK && saved_int_regs != 0)    return 0;  /* On StrongARM, conditional returns are expensive if they aren't     taken and multiple registers have been stacked.  */  if (iscond && arm_is_strong)    {      /* Conditional return when just the LR is stored is a simple 	 conditional-load instruction, that's not expensive.  */      if (saved_int_regs != 0 && saved_int_regs != (1 << LR_REGNUM))	return 0;      if (flag_pic && regs_ever_live[PIC_OFFSET_TABLE_REGNUM])	return 0;    }  /* If there are saved registers but the LR isn't saved, then we need     two instructions for the return.  */  if (saved_int_regs && !(saved_int_regs & (1 << LR_REGNUM)))    return 0;  /* Can't be done if any of the FPU regs are pushed,     since this also requires an insn.  */  if (TARGET_HARD_FLOAT)    for (regno = FIRST_ARM_FP_REGNUM; regno <= LAST_ARM_FP_REGNUM; regno++)      if (regs_ever_live[regno] && !call_used_regs[regno])	return 0;  return 1;}/* Return TRUE if int I is a valid immediate ARM constant.  */intconst_ok_for_arm (i)     HOST_WIDE_INT i;{  unsigned HOST_WIDE_INT mask = ~(unsigned HOST_WIDE_INT)0xFF;  /* For machines with >32 bit HOST_WIDE_INT, the bits above bit 31 must      be all zero, or all one.  */  if ((i & ~(unsigned HOST_WIDE_INT) 0xffffffff) != 0      && ((i & ~(unsigned HOST_WIDE_INT) 0xffffffff)	  != ((~(unsigned HOST_WIDE_INT) 0)	      & ~(unsigned HOST_WIDE_INT) 0xffffffff)))    return FALSE;    /* Fast return for 0 and powers of 2 */  if ((i & (i - 1)) == 0)    return TRUE;  do    {      if ((i & mask & (unsigned HOST_WIDE_INT) 0xffffffff) == 0)        return TRUE;      mask =	  (mask << 2) | ((mask & (unsigned HOST_WIDE_INT) 0xffffffff)			  >> (32 - 2)) | ~(unsigned HOST_WIDE_INT) 0xffffffff;    }  while (mask != ~(unsigned HOST_WIDE_INT) 0xFF);  return FALSE;}/* Return true if I is a valid constant for the operation CODE.  */static intconst_ok_for_op (i, code)     HOST_WIDE_INT i;     enum rtx_code code;{  if (const_ok_for_arm (i))    return 1;  switch (code)    {    case PLUS:      return const_ok_for_arm (ARM_SIGN_EXTEND (-i));    case MINUS:		/* Should only occur with (MINUS I reg) => rsb */    case XOR:    case IOR:      return 0;    case AND:      return const_ok_for_arm (ARM_SIGN_EXTEND (~i));    default:      abort ();    }}/* Emit a sequence of insns to handle a large constant.   CODE is the code of the operation required, it can be any of SET, PLUS,   IOR, AND, XOR, MINUS;   MODE is the mode in which the operation is being performed;   VAL is the integer to operate on;   SOURCE is the other operand (a register, or a null-pointer for SET);   SUBTARGETS means it is safe to create scratch registers if that will   either produce a simpler sequence, or we will want to cse the values.   Return value is the number of insns emitted.  */intarm_split_constant (code, mode, val, target, source, subtargets)     enum rtx_code code;     enum machine_mode mode;     HOST_WIDE_INT val;     rtx target;     rtx source;     int subtargets;{  if (subtargets || code == SET      || (GET_CODE (target) == REG && GET_CODE (source) == REG	  && REGNO (target) != REGNO (source)))    {      /* After arm_reorg has been called, we can't fix up expensive	 constants by pushing them into memory so we must synthesize	 them in-line, regardless of the cost.  This is only likely to	 be more costly on chips that have load delay slots and we are	 compiling without running the scheduler (so no splitting	 occurred before the final instruction emission).	 Ref: gcc -O1 -mcpu=strongarm gcc.c-torture/compile/980506-2.c      */      if (!after_arm_reorg	  && (arm_gen_constant (code, mode, val, target, source, 1, 0)	      > arm_constant_limit + (code != SET)))	{	  if (code == SET)	    {	      /* Currently SET is the only monadic value for CODE, all		 the rest are diadic.  */	      emit_insn (gen_rtx_SET (VOIDmode, target, GEN_INT (val)));	      return 1;	    }	  else	    {	      rtx temp = subtargets ? gen_reg_rtx (mode) : target;	      emit_insn (gen_rtx_SET (VOIDmode, temp, GEN_INT (val)));	      /* For MINUS, the value is subtracted from, since we never		 have subtraction of a constant.  */	      if (code == MINUS)		emit_insn (gen_rtx_SET (VOIDmode, target,					gen_rtx_MINUS (mode, temp, source)));	      else		emit_insn (gen_rtx_SET (VOIDmode, target,					gen_rtx (code, mode, source, temp)));	      return 2;	    }	}    }  return arm_gen_constant (code, mode, val, target, source, subtargets, 1);}static intcount_insns_for_constant (remainder, i)     HOST_WIDE_INT remainder;     int i;{  HOST_WIDE_INT temp1;  int num_insns = 0;  do    {      int end;	        if (i <= 0)	i += 32;      if (remainder & (3 << (i - 2)))	{	  end = i - 8;	  if (end < 0)	    end += 32;	  temp1 = remainder & ((0x0ff << end)				    | ((i < end) ? (0xff >> (32 - end)) : 0));	  remainder &= ~temp1;	  num_insns++;	  i -= 6;	}      i -= 2;    } while (remainder);  return num_insns;}/* As above, but extra parameter GENERATE which, if clear, suppresses   RTL generation.  */static intarm_gen_constant (code, mode, val, target, source, subtargets, generate)     enum rtx_code code;     enum machine_mode mode;     HOST_WIDE_INT val;     rtx target;     rtx source;     int subtargets;     int generate;{  int can_invert = 0;  int can_negate = 0;  int can_negate_initial = 0;  int can_shift = 0;  int i;  int num_bits_set = 0;  int set_sign_bit_copies = 0;  int clear_sign_bit_copies = 0;  int clear_zero_bit_copies = 0;  int set_zero_bit_copies = 0;  int insns = 0;  unsigned HOST_WIDE_INT temp1, temp2;  unsigned HOST_WIDE_INT remainder = val & 0xffffffff;  /* Find out which operations are safe for a given CODE.  Also do a quick     check for degenerate cases; these can occur when DImode operations     are split.  */  switch (code)    {    case SET:      can_invert = 1;      can_shift = 1;      can_negate = 1;      break;    case PLUS:      can_negate = 1;      can_negate_initial = 1;      break;    case IOR:      if (remainder == 0xffffffff)	{	  if (generate)	    emit_insn (gen_rtx_SET (VOIDmode, target,				    GEN_INT (ARM_SIGN_EXTEND (val))));	  return 1;	}      if (remainder == 0)	{	  if (reload_completed && rtx_equal_p (target, source))	    return 0;	  if (generate)	    emit_insn (gen_rtx_SET (VOIDmode, target, source));	  return 1;	}      break;    case AND:      if (remainder == 0)	{	  if (generate)	    emit_insn (gen_rtx_SET (VOIDmode, target, const0_rtx));	  return 1;	}      if (remainder == 0xffffffff)	{	  if (reload_completed && rtx_equal_p (target, source))	    return 0;	  if (generate)	    emit_insn (gen_rtx_SET (VOIDmode, target, source));	  return 1;	}      can_invert = 1;      break;    case XOR:      if (remainder == 0)	{	  if (reload_completed && rtx_equal_p (target, source))	    return 0;	  if (generate)	    emit_insn (gen_rtx_SET (VOIDmode, target, source));	  return 1;	}      if (remainder == 0xffffffff)	{	  if (generate)	    emit_insn (gen_rtx_SET (VOIDmode, target,				    gen_rtx_NOT (mode, source)));	  return 1;	}      /* We don't know how to handle this yet below.  */      abort ();    case MINUS:      /* We treat MINUS as (val - source), since (source - val) is always	 passed as (source + (-val)).  */      if (remainder == 0)	{	  if (generate)	    emit_insn (gen_rtx_SET (VOIDmode, target,				    gen_rtx_NEG (mode, source)));	  return 1;	}      if (const_ok_for_arm (val))	{	  if (generate)	    emit_insn (gen_rtx_SET (VOIDmode, target, 				    gen_rtx_MINUS (mode, GEN_INT (val),						   source)));	  return 1;	}      can_negate = 1;      break;    default:      abort ();    }  /* If we can do it in one insn get out quickly.  */  if (const_ok_for_arm (val)      || (can_negate_initial && const_ok_for_arm (-val))      || (can_invert && const_ok_for_arm (~val)))    {      if (generate)	emit_insn (gen_rtx_SET (VOIDmode, target,				(source ? gen_rtx (code, mode, source,						   GEN_INT (val))				 : GEN_INT (val))));      return 1;    }  /* Calculate a few attributes that may be useful for specific     optimizations.  */  for (i = 31; i >= 0; i--)    {      if ((remainder & (1 << i)) == 0)	clear_sign_bit_copies++;      else	break;    }  for (i = 31; i >= 0; i--)    {      if ((remainder & (1 << i)) != 0)	set_sign_bit_copies++;      else	break;    }  for (i = 0; i <= 31; i++)    {      if ((remainder & (1 << i)) == 0)	clear_zero_bit_copies++;      else	break;    }  for (i = 0; i <= 31; i++)    {      if ((remainder & (1 << i)) != 0)	set_zero_bit_copies++;      else	break;

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -