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

📄 alpha.c

📁 GCC编译器源代码
💻 C
📖 第 1 页 / 共 5 页
字号:
	  value = CONST_DOUBLE_HIGH (x);	  for (i = 0; i < HOST_BITS_PER_WIDE_INT / HOST_BITS_PER_CHAR;	       i++, value >>= 8)	    if (value & 0xff)	      mask |= (1 << (i + sizeof (int)));	  fprintf (file, HOST_WIDE_INT_PRINT_DEC, mask & 0xff);	}      else if (GET_CODE (x) == CONST_INT)	{	  HOST_WIDE_INT mask = 0, value = INTVAL (x);	  for (i = 0; i < 8; i++, value >>= 8)	    if (value & 0xff)	      mask |= (1 << i);	  fprintf (file, HOST_WIDE_INT_PRINT_DEC, mask);	}      else	output_operand_lossage ("invalid %%m value");      break;    case 'M':      /* 'b', 'w', or 'l' as the value of the constant.  */      if (GET_CODE (x) != CONST_INT	  || (INTVAL (x) != 8 && INTVAL (x) != 16 && INTVAL (x) != 32))	output_operand_lossage ("invalid %%M value");      fprintf (file, "%s",	       INTVAL (x) == 8 ? "b" : INTVAL (x) == 16 ? "w" : "l");      break;    case 'U':      /* Similar, except do it from the mask.  */      if (GET_CODE (x) == CONST_INT && INTVAL (x) == 0xff)	fprintf (file, "b");      else if (GET_CODE (x) == CONST_INT && INTVAL (x) == 0xffff)	fprintf (file, "w");#if HOST_BITS_PER_WIDE_INT == 32      else if (GET_CODE (x) == CONST_DOUBLE	       && CONST_DOUBLE_HIGH (x) == 0	       && CONST_DOUBLE_LOW (x) == -1)	fprintf (file, "l");#else      else if (GET_CODE (x) == CONST_INT && INTVAL (x) == 0xffffffff)	fprintf (file, "l");#endif      else	output_operand_lossage ("invalid %%U value");      break;    case 's':      /* Write the constant value divided by 8.  */      if (GET_CODE (x) != CONST_INT	  && (unsigned HOST_WIDE_INT) INTVAL (x) >= 64	  && (INTVAL (x) & 7) != 8)	output_operand_lossage ("invalid %%s value");      fprintf (file, HOST_WIDE_INT_PRINT_DEC, INTVAL (x) / 8);      break;    case 'S':      /* Same, except compute (64 - c) / 8 */      if (GET_CODE (x) != CONST_INT	  && (unsigned HOST_WIDE_INT) INTVAL (x) >= 64	  && (INTVAL (x) & 7) != 8)	output_operand_lossage ("invalid %%s value");      fprintf (file, HOST_WIDE_INT_PRINT_DEC, (64 - INTVAL (x)) / 8);      break;    case 'C': case 'D': case 'c': case 'd':      /* Write out comparison name.  */      {	enum rtx_code c = GET_CODE (x);        if (GET_RTX_CLASS (c) != '<')	  output_operand_lossage ("invalid %%C value");	if (code == 'D')	  c = reverse_condition (c);	else if (code == 'c')	  c = swap_condition (c);	else if (code == 'd')	  c = swap_condition (reverse_condition (c));        if (c == LEU)	  fprintf (file, "ule");        else if (c == LTU)	  fprintf (file, "ult");        else	  fprintf (file, "%s", GET_RTX_NAME (c));      }      break;    case 'E':      /* Write the divide or modulus operator.  */      switch (GET_CODE (x))	{	case DIV:	  fprintf (file, "div%s", GET_MODE (x) == SImode ? "l" : "q");	  break;	case UDIV:	  fprintf (file, "div%su", GET_MODE (x) == SImode ? "l" : "q");	  break;	case MOD:	  fprintf (file, "rem%s", GET_MODE (x) == SImode ? "l" : "q");	  break;	case UMOD:	  fprintf (file, "rem%su", GET_MODE (x) == SImode ? "l" : "q");	  break;	default:	  output_operand_lossage ("invalid %%E value");	  break;	}      break;    case 'A':      /* Write "_u" for unaligned access.  */      if (GET_CODE (x) == MEM && GET_CODE (XEXP (x, 0)) == AND)	fprintf (file, "_u");      break;    case 0:      if (GET_CODE (x) == REG)	fprintf (file, "%s", reg_names[REGNO (x)]);      else if (GET_CODE (x) == MEM)	output_address (XEXP (x, 0));      else	output_addr_const (file, x);      break;    default:      output_operand_lossage ("invalid %%xn code");    }}/* Do what is necessary for `va_start'.  The argument is ignored;   We look at the current function to determine if stdarg or varargs   is used and fill in an initial va_list.  A pointer to this constructor   is returned.  */struct rtx_def *alpha_builtin_saveregs (arglist)     tree arglist;{  rtx block, addr, dest, argsize;  tree fntype = TREE_TYPE (current_function_decl);  int stdarg = (TYPE_ARG_TYPES (fntype) != 0		&& (TREE_VALUE (tree_last (TYPE_ARG_TYPES (fntype)))		    != void_type_node));  /* Compute the current position into the args, taking into account     both registers and memory.  Both of these are already included in     NUM_ARGS.  */  argsize = GEN_INT (NUM_ARGS * UNITS_PER_WORD);  /* For Unix, SETUP_INCOMING_VARARGS moves the starting address base up by 48,     storing fp arg registers in the first 48 bytes, and the integer arg     registers in the next 48 bytes.  This is only done, however, if any     integer registers need to be stored.     If no integer registers need be stored, then we must subtract 48 in     order to account for the integer arg registers which are counted in     argsize above, but which are not actually stored on the stack.  */  if (TARGET_OPEN_VMS)    addr = plus_constant (virtual_incoming_args_rtx,			  NUM_ARGS <= 5 + stdarg			  ? UNITS_PER_WORD : - 6 * UNITS_PER_WORD);  else    addr = (NUM_ARGS <= 5 + stdarg	    ? plus_constant (virtual_incoming_args_rtx,			     6 * UNITS_PER_WORD)	    : plus_constant (virtual_incoming_args_rtx,			     - (6 * UNITS_PER_WORD)));  /* For VMS, we include the argsize, while on Unix, it's handled as     a separate field.  */  if (TARGET_OPEN_VMS)    addr = plus_constant (addr, INTVAL (argsize));  addr = force_operand (addr, NULL_RTX);#ifdef POINTERS_EXTEND_UNSIGNED  addr = convert_memory_address (ptr_mode, addr);#endif  if (TARGET_OPEN_VMS)    return addr;  else    {      /* Allocate the va_list constructor */      block = assign_stack_local (BLKmode, 2 * UNITS_PER_WORD, BITS_PER_WORD);      RTX_UNCHANGING_P (block) = 1;      RTX_UNCHANGING_P (XEXP (block, 0)) = 1;      /* Store the address of the first integer register in the __base	 member.  */      dest = change_address (block, ptr_mode, XEXP (block, 0));      emit_move_insn (dest, addr);      if (flag_check_memory_usage)	emit_library_call (chkr_set_right_libfunc, 1, VOIDmode, 3,			   dest, ptr_mode,			   GEN_INT (GET_MODE_SIZE (ptr_mode)),			   TYPE_MODE (sizetype),			   GEN_INT (MEMORY_USE_RW), 			   TYPE_MODE (integer_type_node));        /* Store the argsize as the __va_offset member.  */      dest = change_address (block, TYPE_MODE (integer_type_node),			     plus_constant (XEXP (block, 0),					    POINTER_SIZE/BITS_PER_UNIT));      emit_move_insn (dest, argsize);      if (flag_check_memory_usage)	emit_library_call (chkr_set_right_libfunc, 1, VOIDmode, 3,			   dest, ptr_mode,			   GEN_INT (GET_MODE_SIZE				    (TYPE_MODE (integer_type_node))),			   TYPE_MODE (sizetype),			   GEN_INT (MEMORY_USE_RW),			   TYPE_MODE (integer_type_node));      /* Return the address of the va_list constructor, but don't put it in a	 register.  Doing so would fail when not optimizing and produce worse	 code when optimizing.  */      return XEXP (block, 0);    }}#if OPEN_VMS#define REG_PV 27#define REG_RA 26#else#define REG_RA 26#endif/* Find the current function's return address.   ??? It would be better to arrange things such that if we would ordinarily   have been a leaf function and we didn't spill the hard reg that we   wouldn't have to save the register in the prolog.  But it's not clear   how to get the right information at the right time.  */static rtx alpha_return_addr_rtx;rtxalpha_return_addr (){  rtx ret;  if ((ret = alpha_return_addr_rtx) == NULL)    {      alpha_return_addr_rtx = ret = gen_reg_rtx (Pmode);      emit_insn_after (gen_rtx (SET, VOIDmode, ret,			        gen_rtx (REG, Pmode, REG_RA)),		       get_insns ());    }  return ret;}/* This page contains routines that are used to determine what the function   prologue and epilogue code will do and write them out.  *//* Compute the size of the save area in the stack.  */#if OPEN_VMS/* These variables are used for communication between the following functions.   They indicate various things about the current function being compiled   that are used to tell what kind of prologue, epilogue and procedure   descriptior to generate. *//* Nonzero if we need a stack procedure.  */static int is_stack_procedure;/* Register number (either FP or SP) that is used to unwind the frame.  */static int unwind_regno;/* Register number used to save FP.  We need not have one for RA since   we don't modify it for register procedures.  This is only defined   for register frame procedures.  */static int save_fp_regno;/* Register number used to reference objects off our PV.  */static int base_regno;/*  Compute register masks for saved registers.  */static voidalpha_sa_mask (imaskP, fmaskP)    unsigned long *imaskP;    unsigned long *fmaskP;{  unsigned long imask = 0;  unsigned long fmask = 0;  int i;  if (is_stack_procedure)    imask |= (1L << HARD_FRAME_POINTER_REGNUM);  /* One for every register we have to save.  */  for (i = 0; i < FIRST_PSEUDO_REGISTER; i++)    if (! fixed_regs[i] && ! call_used_regs[i] && regs_ever_live[i])      {	if (i < 32)	  imask |= (1L << i);	else	  fmask |= (1L << (i - 32));      }  *imaskP = imask;  *fmaskP = fmask;  return;}intalpha_sa_size (){  int sa_size = 0;  HOST_WIDE_INT stack_needed;  int i;  /* One for every register we have to save.  */  for (i = 0; i < FIRST_PSEUDO_REGISTER; i++)    if (! fixed_regs[i] && ! call_used_regs[i] && regs_ever_live[i])      sa_size++;  /* Start by assuming we can use a register procedure if we don't make any     calls (REG_RA not used) or need to save any registers and a stack     procedure if we do.  */  is_stack_procedure = regs_ever_live[REG_RA] || sa_size != 0;  /* Decide whether to refer to objects off our PV via FP or PV.     If we need need FP for something else or if we receive a nonlocal     goto (which expects PV to contain the value), we must use PV.     Otherwise, start by assuming we can use FP.  */  base_regno = (frame_pointer_needed || current_function_has_nonlocal_label		|| is_stack_procedure		|| current_function_outgoing_args_size		? REG_PV : HARD_FRAME_POINTER_REGNUM);  /* If we want to copy PV into FP, we need to find some register in which to     save FP.  */  save_fp_regno = -1;  if (base_regno == HARD_FRAME_POINTER_REGNUM)    for (i = 0; i < 32; i++)      if (! fixed_regs[i] && call_used_regs[i] && ! regs_ever_live[i])	save_fp_regno = i;  if (save_fp_regno == -1)    base_regno = REG_PV, is_stack_procedure = 1;  /* Stack unwinding should be done via FP unless we use it for PV.  */  unwind_regno    = base_regno == REG_PV ? HARD_FRAME_POINTER_REGNUM : STACK_POINTER_REGNUM;  /* If this is a stack procedure, allow space for saving FP and RA.  */  if (is_stack_procedure)    sa_size += 2;  return sa_size * 8;}intalpha_pv_save_size (){  alpha_sa_size ();  return is_stack_procedure ? 8 : 0;}intalpha_using_fp (){  alpha_sa_size ();  return unwind_regno == HARD_FRAME_POINTER_REGNUM;}#else /* ! OPEN_VMS */intalpha_sa_size (){  int size = 0;  int i;  for (i = 0; i < FIRST_PSEUDO_REGISTER; i++)    if (! fixed_regs[i] && ! call_used_regs[i] && regs_ever_live[i])      size++;  /* If some registers were saved but not reg 26, reg 26 must also     be saved, so leave space for it.  */  if (size != 0 && ! regs_ever_live[26])    size++;  /* Our size must be even (multiple of 16 bytes).  */  if (size & 1)    size ++;  return size * 8;}#endif /* ! OPEN_VMS *//* Return 1 if this function can directly return via $26.  */intdirect_return (){  return (! TARGET_OPEN_VMS && reload_completed && alpha_sa_size () == 0	  && get_frame_size () == 0	  && current_function_outgoing_args_size == 0	  && current_function_pretend_args_size == 0);}/* Write a version stamp.  Don't write anything if we are running as a   cross-compiler.  Otherwise, use the versions in /usr/include/stamp.h.  */#if !defined(CROSS_COMPILE) && !defined(_WIN32) && !defined(__linux__) && !defined(VMS)#include <stamp.h>#endifvoidalpha_write_verstamp (file)     FILE *file;{#ifdef MS_STAMP  fprintf (file, "\t.verstamp %d %d\n", MS_STAMP, LS_STAMP);#endif}/* Write code to add constant C to register number IN_REG (possibly 31)   and put the result into OUT_REG.  Use TEMP_REG as a scratch register;   usually this will be OUT_REG, but should not be if OUT_REG is    STACK_POINTER_REGNUM, since it must be updated in a single instruction.   Write the code to FILE.  */static voidadd_long_const (file, c, in_reg, out_reg, temp_reg)     FILE *file;     HOST_WIDE_INT c;     int in_reg, out_reg, temp_reg;{  HOST_WIDE_INT low = (c & 0xffff) - 2 * (c & 0x8000);  HOST_WIDE_INT tmp1 = c - low;  HOST_WIDE_INT high = ((tmp1 >> 16) & 0xffff) - 2 * ((tmp1 >> 16) & 0x8000);  HOST_WIDE_INT extra = 0;  /* We don't have code to write out constants larger than 32 bits.  */#if HOST_BITS_PER_LONG_INT == 64  if ((unsigned HOST_WIDE_INT) c >> 32 != 0)    abort ();#endif  /* If HIGH will be interpreted as negative, we must adjust it to do two     ldha insns.  Note that we will never be building a negative constant     here.  */

⌨️ 快捷键说明

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