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

📄 v850.c

📁 gcc-2.95.3 Linux下最常用的C编译器
💻 C
📖 第 1 页 / 共 5 页
字号:
    case FUNCTION_DECL:      area = v850_get_data_area (decl);      if (area != DATA_AREA_NORMAL && data_area != area)	error_with_decl (decl, "\data area of '%s' conflicts with previous declaration");            return 1;          default:      break;    }    return 0;}/* Return nonzero if FUNC is an interrupt function as specified   by the "interrupt" attribute.  */intv850_interrupt_function_p (func)     tree func;{  tree a;  int ret = 0;  if (v850_interrupt_cache_p)    return v850_interrupt_p;  if (TREE_CODE (func) != FUNCTION_DECL)    return 0;  a = lookup_attribute ("interrupt_handler", DECL_MACHINE_ATTRIBUTES (func));  if (a != NULL_TREE)    ret = 1;  else    {      a = lookup_attribute ("interrupt", DECL_MACHINE_ATTRIBUTES (func));      ret = a != NULL_TREE;    }  /* Its not safe to trust global variables until after function inlining has     been done.  */  if (reload_completed | reload_in_progress)    v850_interrupt_p = ret;  return ret;}extern struct obstack * saveable_obstack;voidv850_encode_data_area (decl)     tree decl;{  char * str = XSTR (XEXP (DECL_RTL (decl), 0), 0);  int    len = strlen (str);  char * newstr;  /* Map explict sections into the appropriate attribute */  if (v850_get_data_area (decl) == DATA_AREA_NORMAL)    {      if (DECL_SECTION_NAME (decl))	{	  char * name = TREE_STRING_POINTER (DECL_SECTION_NAME (decl));	  	  if (streq (name, ".zdata") || streq (name, ".zbss"))	    v850_set_data_area (decl, DATA_AREA_ZDA);	  else if (streq (name, ".sdata") || streq (name, ".sbss"))	    v850_set_data_area (decl, DATA_AREA_SDA);	  else if (streq (name, ".tdata"))	    v850_set_data_area (decl, DATA_AREA_TDA);	}      /* If no attribute, support -m{zda,sda,tda}=n */      else	{	  int size = int_size_in_bytes (TREE_TYPE (decl));	  if (size <= 0)	    ;	  else if (size <= small_memory [(int) SMALL_MEMORY_TDA].max)	    v850_set_data_area (decl, DATA_AREA_TDA);	  else if (size <= small_memory [(int) SMALL_MEMORY_SDA].max)	    v850_set_data_area (decl, DATA_AREA_SDA);	  else if (size <= small_memory [(int) SMALL_MEMORY_ZDA].max)	    v850_set_data_area (decl, DATA_AREA_ZDA);	}            if (v850_get_data_area (decl) == DATA_AREA_NORMAL)	return;    }  newstr = obstack_alloc (saveable_obstack, len + 2);  strcpy (newstr + 1, str);  switch (v850_get_data_area (decl))    {    case DATA_AREA_ZDA: *newstr = ZDA_NAME_FLAG_CHAR; break;    case DATA_AREA_TDA: *newstr = TDA_NAME_FLAG_CHAR; break;    case DATA_AREA_SDA: *newstr = SDA_NAME_FLAG_CHAR; break;    default: abort ();    }  XSTR (XEXP (DECL_RTL (decl), 0), 0) = newstr;}/* Return true if the given RTX is a register which can be restored   by a function epilogue.  */intregister_is_ok_for_epilogue (op, mode)     rtx op;     enum machine_mode ATTRIBUTE_UNUSED mode;{  /* The save/restore routines can only cope with registers 2, and 20 - 31 */  return (GET_CODE (op) == REG)	  && (((REGNO (op) >= 20) && REGNO (op) <= 31)	      || REGNO (op) == 2);}/* Return non-zero if the given RTX is suitable for collapsing into   jump to a function epilogue.  */intpattern_is_ok_for_epilogue (op, mode)     rtx op;     enum machine_mode ATTRIBUTE_UNUSED mode;{  int count = XVECLEN (op, 0);  int i;    /* If there are no registers to restore then the function epilogue     is not suitable.  */  if (count <= 2)    return 0;  /* The pattern matching has already established that we are performing a     function epilogue and that we are popping at least one register.  We must     now check the remaining entries in the vector to make sure that they are     also register pops.  There is no good reason why there should ever be     anything else in this vector, but being paranoid always helps...     The test below performs the C equivalent of this machine description     pattern match:        (set (match_operand:SI n "register_is_ok_for_epilogue" "r")	  (mem:SI (plus:SI (reg:SI 3) (match_operand:SI n "immediate_operand" "i"))))     */  for (i = 3; i < count; i++)    {      rtx vector_element = XVECEXP (op, 0, i);      rtx dest;      rtx src;      rtx plus;            if (GET_CODE (vector_element) != SET)	return 0;            dest = SET_DEST (vector_element);      src = SET_SRC (vector_element);      if (GET_CODE (dest) != REG	  || GET_MODE (dest) != SImode	  || ! register_is_ok_for_epilogue (dest, SImode)	  || GET_CODE (src) != MEM	  || GET_MODE (src) != SImode)	return 0;      plus = XEXP (src, 0);      if (GET_CODE (plus) != PLUS	  || GET_CODE (XEXP (plus, 0)) != REG	  || GET_MODE (XEXP (plus, 0)) != SImode	  || REGNO (XEXP (plus, 0)) != STACK_POINTER_REGNUM	  || GET_CODE (XEXP (plus, 1)) != CONST_INT)	return 0;    }  return 1;}/* Construct a JR instruction to a routine that will perform the equivalent of   the RTL passed in as an argument.  This RTL is a function epilogue that   pops registers off the stack and possibly releases some extra stack space   as well.  The code has already verified that the RTL matches these   requirements.  */char *construct_restore_jr (op)     rtx op;{  int count = XVECLEN (op, 0);  int stack_bytes;  unsigned long int mask;  unsigned long int first;  unsigned long int last;  int i;  static char buff [100]; /* XXX */    if (count <= 2)    {      error ("Bogus JR construction: %d\n", count);      return NULL;    }  /* Work out how many bytes to pop off the stack before retrieving     registers.  */  if (GET_CODE (XVECEXP (op, 0, 1)) != SET)    abort ();  if (GET_CODE (SET_SRC (XVECEXP (op, 0, 1))) != PLUS)    abort ();  if (GET_CODE (XEXP (SET_SRC (XVECEXP (op, 0, 1)), 1)) != CONST_INT)    abort ();      stack_bytes = INTVAL (XEXP (SET_SRC (XVECEXP (op, 0, 1)), 1));  /* Each pop will remove 4 bytes from the stack... */  stack_bytes -= (count - 2) * 4;  /* Make sure that the amount we are popping either 0 or 16 bytes.  */  if (stack_bytes != 0 && stack_bytes != 16)    {      error ("Bad amount of stack space removal: %d", stack_bytes);      return NULL;    }  /* Now compute the bit mask of registers to push.  */  mask = 0;  for (i = 2; i < count; i++)    {      rtx vector_element = XVECEXP (op, 0, i);            if (GET_CODE (vector_element) != SET)	abort ();      if (GET_CODE (SET_DEST (vector_element)) != REG)	abort ();      if (! register_is_ok_for_epilogue (SET_DEST (vector_element), SImode))	abort ();            mask |= 1 << REGNO (SET_DEST (vector_element));    }  /* Scan for the first register to pop.  */  for (first = 0; first < 32; first++)    {      if (mask & (1 << first))	break;    }  if (first >= 32)    abort ();  /* Discover the last register to pop.  */  if (mask & (1 << LINK_POINTER_REGNUM))    {      if (stack_bytes != 16)	abort ();            last = LINK_POINTER_REGNUM;    }  else    {      if (stack_bytes != 0)	abort ();            if ((mask & (1 << 29)) == 0)	abort ();            last = 29;    }  /* Note, it is possible to have gaps in the register mask.     We ignore this here, and generate a JR anyway.  We will     be popping more registers than is strictly necessary, but     it does save code space.  */    if (TARGET_LONG_CALLS)    {      char name[40];            if (first == last)	sprintf (name, "__return_%s", reg_names [first]);      else	sprintf (name, "__return_%s_%s", reg_names [first], reg_names [last]);            sprintf (buff, "movhi hi(%s), r0, r6\n\tmovea lo(%s), r6, r6\n\tjmp r6",	       name, name);    }  else    {      if (first == last)	sprintf (buff, "jr __return_%s", reg_names [first]);      else	sprintf (buff, "jr __return_%s_%s", reg_names [first], reg_names [last]);    }    return buff;}/* Return non-zero if the given RTX is suitable for collapsing into   a jump to a function prologue.  */intpattern_is_ok_for_prologue (op, mode)     rtx op;     enum machine_mode ATTRIBUTE_UNUSED mode;{  int count = XVECLEN (op, 0);  int i;   rtx vector_element;   /* If there are no registers to save then the function prologue     is not suitable.  */  if (count <= 2)    return 0;  /* The pattern matching has already established that we are adjusting the     stack and pushing at least one register.  We must now check that the     remaining entries in the vector to make sure that they are also register     pushes, except for the last entry which should be a CLOBBER of r10.     The test below performs the C equivalent of this machine description     pattern match:     (set (mem:SI (plus:SI (reg:SI 3)      (match_operand:SI 2 "immediate_operand" "i")))      (match_operand:SI 3 "register_is_ok_for_epilogue" "r"))     */  for (i = 2; i < count - 1; i++)    {      rtx dest;      rtx src;      rtx plus;            vector_element = XVECEXP (op, 0, i);            if (GET_CODE (vector_element) != SET)	return 0;            dest = SET_DEST (vector_element);      src = SET_SRC (vector_element);      if (GET_CODE (dest) != MEM	  || GET_MODE (dest) != SImode	  || GET_CODE (src) != REG	  || GET_MODE (src) != SImode	  || ! register_is_ok_for_epilogue (src, SImode))	return 0;      plus = XEXP (dest, 0);      if ( GET_CODE (plus) != PLUS	  || GET_CODE (XEXP (plus, 0)) != REG	  || GET_MODE (XEXP (plus, 0)) != SImode	  || REGNO (XEXP (plus, 0)) != STACK_POINTER_REGNUM	  || GET_CODE (XEXP (plus, 1)) != CONST_INT)	return 0;      /* If the register is being pushed somewhere other than the stack	 space just acquired by the first operand then abandon this quest.	 Note: the test is <= because both values are negative.	 */      if (INTVAL (XEXP (plus, 1))	  <= INTVAL (XEXP (SET_SRC (XVECEXP (op, 0, 0)), 1)))	{	  return 0;	}    }  /* Make sure that the last entry in the vector is a clobber.  */  vector_element = XVECEXP (op, 0, i);    if (GET_CODE (vector_element) != CLOBBER      || GET_CODE (XEXP (vector_element, 0)) != REG      || REGNO (XEXP (vector_element, 0)) != 10)    return 0;    return 1;}/* Construct a JARL instruction to a routine that will perform the equivalent   of the RTL passed as a parameter.  This RTL is a function prologue that   saves some of the registers r20 - r31 onto the stack, and possibly acquires   some stack space as well.  The code has already verified that the RTL   matches these requirements.  */char *construct_save_jarl (op)     rtx op;{  int count = XVECLEN (op, 0);  int stack_bytes;  unsigned long int mask;  unsigned long int first;  unsigned long int last;  int i;  static char buff [100]; /* XXX */    if (count <= 2)    {      error ("Bogus JARL construction: %d\n", count);      return NULL;    }  /* Paranoia.  */  if (GET_CODE (XVECEXP (op, 0, 0)) != SET)    abort ();  if (GET_CODE (SET_SRC (XVECEXP (op, 0, 0))) != PLUS)    abort ();  if (GET_CODE (XEXP (SET_SRC (XVECEXP (op, 0, 0)), 0)) != REG)    abort ();  if (GET_CODE (XEXP (SET_SRC (XVECEXP (op, 0, 0)), 1)) != CONST_INT)    abort ();      /* Work out how many bytes to push onto the stack after storing the     registers.  */  stack_bytes = INTVAL (XEXP (SET_SRC (XVECEXP (op, 0, 0)), 1));  /* Each push will put 4 bytes from the stack... */  stack_bytes += (count - 2) * 4;  /* Make sure that the amount we are popping either 0 or 16 bytes.  */  if (stack_bytes != 0 && stack_bytes != -16)    {      error ("Bad amount of stack space removal: %d", stack_bytes);      return NULL;    }  /* Now compute the bit mask of registers to push.  */  mask = 0;  for (i = 1; i < count - 1; i++)    {      rtx vector_element = XVECEXP (op, 0, i);            if (GET_CODE (vector_element) != SET)	abort ();      if (GET_CODE (SET_SRC (vector_element)) != REG)	abort ();      if (! register_is_ok_for_epilogue (SET_SRC (vector_element), SImode))	abort ();            mask |= 1 << REGNO (SET_SRC (vector_element));    }  /* Scan for the first register to push.  */    for (first = 0; first < 32; first++)    {      if (mask & (1 << first))	break;    }  if (first >= 32)    abort ();  /* Discover the last register to push.  */  if (mask & (1 << LINK_POINTER_REGNUM))    {      if (stack_bytes != -16)	abort ();            last = LINK_POINTER_REGNUM;    }  else    {      if (stack_bytes != 0)	abort ();      if ((mask & (1 << 29)) == 0)	abort ();            last = 29;    }  /* Note, it is possible to have gaps in the register mask.     We ignore this here, and generate a JARL anyway.  We will     be pushing more registers than is strictly necessary, but     it does save code space.  */    if (TARGET_LONG_CALLS)    {      char name[40];            if (first == last)	sprintf (name, "__save_%s", reg_names [first]);      else	sprintf (name, "__save_%s_%s", reg_names [first], reg_names [last]);            sprintf (buff, "movhi hi(%s), r0, r11\n\tmovea lo(%s), r11, r11\n\tjarl .+4, r10\n\tadd 4, r10\n\tjmp r11",	       name, name);    }  else    {      if (first == last)	sprintf (buff, "jarl __save_%s, r10", reg_names [first]);      else	sprintf (buff, "jarl __save_%s_%s, r10", reg_names [first],		 reg_names [last]);    }  return buff;}extern tree last_assemble_variable_decl;extern int size_directive_output;/* A version of asm_output_aligned_bss() that copes with the special   data areas of the v850. */voidv850_output_aligned_bss (file, decl, name, size, align)     FILE * file;     tree decl;     c

⌨️ 快捷键说明

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