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

📄 v850.c

📁 linux下编程用 编译软件
💻 C
📖 第 1 页 / 共 5 页
字号:
    case CC_CLOBBER:      /* Insn doesn't leave CC in a usable state.  */      CC_STATUS_INIT;      break;    }}/* Retrieve the data area that has been chosen for the given decl.  */v850_data_areav850_get_data_area (tree decl){  if (lookup_attribute ("sda", DECL_ATTRIBUTES (decl)) != NULL_TREE)    return DATA_AREA_SDA;    if (lookup_attribute ("tda", DECL_ATTRIBUTES (decl)) != NULL_TREE)    return DATA_AREA_TDA;    if (lookup_attribute ("zda", DECL_ATTRIBUTES (decl)) != NULL_TREE)    return DATA_AREA_ZDA;  return DATA_AREA_NORMAL;}/* Store the indicated data area in the decl's attributes.  */static voidv850_set_data_area (tree decl, v850_data_area data_area){  tree name;    switch (data_area)    {    case DATA_AREA_SDA: name = get_identifier ("sda"); break;    case DATA_AREA_TDA: name = get_identifier ("tda"); break;    case DATA_AREA_ZDA: name = get_identifier ("zda"); break;    default:      return;    }  DECL_ATTRIBUTES (decl) = tree_cons    (name, NULL, DECL_ATTRIBUTES (decl));}const struct attribute_spec v850_attribute_table[] ={  /* { name, min_len, max_len, decl_req, type_req, fn_type_req, handler } */  { "interrupt_handler", 0, 0, true,  false, false, v850_handle_interrupt_attribute },  { "interrupt",         0, 0, true,  false, false, v850_handle_interrupt_attribute },  { "sda",               0, 0, true,  false, false, v850_handle_data_area_attribute },  { "tda",               0, 0, true,  false, false, v850_handle_data_area_attribute },  { "zda",               0, 0, true,  false, false, v850_handle_data_area_attribute },  { NULL,                0, 0, false, false, false, NULL }};/* Handle an "interrupt" attribute; arguments as in   struct attribute_spec.handler.  */static treev850_handle_interrupt_attribute (tree * node,                                 tree name,                                 tree args ATTRIBUTE_UNUSED,                                 int flags ATTRIBUTE_UNUSED,                                 bool * no_add_attrs){  if (TREE_CODE (*node) != FUNCTION_DECL)    {      warning (OPT_Wattributes, "%qs attribute only applies to functions",	       IDENTIFIER_POINTER (name));      *no_add_attrs = true;    }  return NULL_TREE;}/* Handle a "sda", "tda" or "zda" attribute; arguments as in   struct attribute_spec.handler.  */static treev850_handle_data_area_attribute (tree* node,                                 tree name,                                 tree args ATTRIBUTE_UNUSED,                                 int flags ATTRIBUTE_UNUSED,                                 bool * no_add_attrs){  v850_data_area data_area;  v850_data_area area;  tree decl = *node;  /* Implement data area attribute.  */  if (is_attribute_p ("sda", name))    data_area = DATA_AREA_SDA;  else if (is_attribute_p ("tda", name))    data_area = DATA_AREA_TDA;  else if (is_attribute_p ("zda", name))    data_area = DATA_AREA_ZDA;  else    gcc_unreachable ();    switch (TREE_CODE (decl))    {    case VAR_DECL:      if (current_function_decl != NULL_TREE)	{          error ("%Jdata area attributes cannot be specified for "                 "local variables", decl);	  *no_add_attrs = true;	}      /* Drop through.  */    case FUNCTION_DECL:      area = v850_get_data_area (decl);      if (area != DATA_AREA_NORMAL && data_area != area)	{	  error ("data area of %q+D conflicts with previous declaration",                 decl);	  *no_add_attrs = true;	}      break;          default:      break;    }  return NULL_TREE;}/* Return nonzero if FUNC is an interrupt function as specified   by the "interrupt" attribute.  */intv850_interrupt_function_p (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_ATTRIBUTES (func));  if (a != NULL_TREE)    ret = 1;  else    {      a = lookup_attribute ("interrupt", DECL_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;}static voidv850_encode_data_area (tree decl, rtx symbol){  int flags;  /* Map explicit sections into the appropriate attribute */  if (v850_get_data_area (decl) == DATA_AREA_NORMAL)    {      if (DECL_SECTION_NAME (decl))	{	  const 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;    }  flags = SYMBOL_REF_FLAGS (symbol);  switch (v850_get_data_area (decl))    {    case DATA_AREA_ZDA: flags |= SYMBOL_FLAG_ZDA; break;    case DATA_AREA_TDA: flags |= SYMBOL_FLAG_TDA; break;    case DATA_AREA_SDA: flags |= SYMBOL_FLAG_SDA; break;    default: gcc_unreachable ();    }  SYMBOL_REF_FLAGS (symbol) = flags;}static voidv850_encode_section_info (tree decl, rtx rtl, int first){  default_encode_section_info (decl, rtl, first);  if (TREE_CODE (decl) == VAR_DECL      && (TREE_STATIC (decl) || DECL_EXTERNAL (decl)))    v850_encode_data_area (decl, XEXP (rtl, 0));}/* 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 (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", count);      return NULL;    }  /* Work out how many bytes to pop off the stack before retrieving     registers.  */  gcc_assert (GET_CODE (XVECEXP (op, 0, 1)) == SET);  gcc_assert (GET_CODE (SET_SRC (XVECEXP (op, 0, 1))) == PLUS);  gcc_assert (GET_CODE (XEXP (SET_SRC (XVECEXP (op, 0, 1)), 1)) == CONST_INT);      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);            gcc_assert (GET_CODE (vector_element) == SET);      gcc_assert (GET_CODE (SET_DEST (vector_element)) == REG);      gcc_assert (register_is_ok_for_epilogue (SET_DEST (vector_element),					       SImode));            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;    }  gcc_assert (first < 32);  /* Discover the last register to pop.  */  if (mask & (1 << LINK_POINTER_REGNUM))    {      gcc_assert (stack_bytes == 16);            last = LINK_POINTER_REGNUM;    }  else    {      gcc_assert (!stack_bytes);      gcc_assert (mask & (1 << 29));            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;}/* 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 (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.  */  gcc_assert (GET_CODE (XVECEXP (op, 0, 0)) == SET);  gcc_assert (GET_CODE (SET_SRC (XVECEXP (op, 0, 0))) == PLUS);  gcc_assert (GET_CODE (XEXP (SET_SRC (XVECEXP (op, 0, 0)), 0)) == REG);  gcc_assert (GET_CODE (XEXP (SET_SRC (XVECEXP (op, 0, 0)), 1)) == CONST_INT);      /* 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 - (TARGET_LONG_CALLS ? 3 : 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 - (TARGET_LONG_CALLS ? 2 : 1); i++)    {      rtx vector_element = XVECEXP (op, 0, i);            gcc_assert (GET_CODE (vector_element) == SET);      gcc_assert (GET_CODE (SET_SRC (vector_element)) == REG);      gcc_assert (register_is_ok_for_epilogue (SET_SRC (vector_element),					       SImode));            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;    }  gcc_assert (first < 32);  /* Discover the last register to push.  */  if (mask & (1 << LINK_POINTER_REGNUM))    {      gcc_assert (stack_bytes == -16);            last = LINK_POINTER_REGNUM;    }  else    {      gcc_assert (!stack_bytes);      gcc_assert (mask & (1 << 29));            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 * file,                         tree decl,                         const char * name,                         unsigned HOST_WIDE_INT size,                         int align){  switch (v850_get_data_area (decl))    {    case DATA_AREA_ZDA:      zbss_section ();      break;    case DATA_AREA_SDA:      sbss_section ();      break;    case DATA_AREA_TDA:      tdata_section ();          default:      bss_section ();      break;    }    ASM_OUTPUT_ALIGN (file, floor_log2 (align / BITS_PER_UNIT));#ifdef ASM_DECLARE_OBJECT_NAME  last_assemble_variable_decl = decl;  ASM_DECLARE_OBJECT_NAME (file, name, decl);#else  /* Standard thing is just output label for the object.  */  ASM_OUTPUT_LABEL (file, name);#endif /* ASM_DECLARE_OBJECT_NAME */  ASM_OUTPUT_SKIP (file, size ? size : 1);}/* Called via the macro ASM_OUTPUT_DECL_COMMON */voidv850_output_common (FILE * file,                    tree decl,                    const char * name,                    int size,                    int align){  if (decl == NULL_TREE)    {      fprintf (file, "%s", COMMON_ASM_OP);    }  else    {      switch (v850_get_data_area (decl))	{	case DATA_AREA_ZDA:	  fprintf (file, "%s", ZCOMMON_ASM_OP);	  break;	case DATA_AREA_SDA:	  fprintf (file, "%s", SCOMMON_ASM_OP);	  break;	case DATA_AREA_TDA:	  fprintf (file, "%s", TCOMMON_ASM_OP);	  break;     

⌨️ 快捷键说明

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