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

📄 tc-i370.c

📁 基于4个mips核的noc设计
💻 C
📖 第 1 页 / 共 5 页
字号:
      literals[next_literal_pool_place].exp = *exx;      literals[next_literal_pool_place].size = sz;      literals[next_literal_pool_place].offset = offset_in_pool;      if (name)	{	  literals[next_literal_pool_place].sym_name = strdup (name);	}      else	{	  literals[next_literal_pool_place].sym_name = NULL;	}      next_literal_pool_place++;    }  /* ???_poolP points to the begining of the literal pool.   * X_add_number is the offset from the begining of the   * literal pool to this expr minus the location of the most   * recent .using directive.  Thus, the grand total value of the   * expression is the distance from .using to the literal.   */  if (8 == sz)    exx->X_add_symbol = longlong_poolP;  else if (4 == sz)    exx->X_add_symbol = word_poolP;  else if (2 == sz)    exx->X_add_symbol = short_poolP;  else if (1 == sz)    exx->X_add_symbol = byte_poolP;  exx->X_add_number = offset_in_pool;  exx->X_op_symbol = NULL;  /* If the user has set up a base reg in another section,   * use that; otherwise use the text section.  */  if (0 < i370_using_other_regno)    {      i370_make_relative (exx, &i370_using_other_baseaddr);    }  else    {      i370_make_relative (exx, &i370_using_text_baseaddr);    }}/* The symbol setup for the literal pool is done in two steps.  First, * a symbol that represents the start of the literal pool is created, * above, in the add_to_pool() routine. This sym ???_poolP. * However, we don't know what fragment its in until a bit later. * So we defer the frag_now thing, and the symbol name, until .ltorg time *//* Can't use symbol_new here, so have to create a symbol and then at   a later date assign it a value. Thats what these functions do */static voidsymbol_locate (symbolP, name, segment, valu, frag)     symbolS *symbolP;     CONST char *name;		/* It is copied, the caller can modify */     segT segment;		/* Segment identifier (SEG_<something>) */     valueT valu;		/* Symbol value */     fragS *frag;		/* Associated fragment */{  size_t name_length;  char *preserved_copy_of_name;  name_length = strlen (name) + 1;      /* +1 for \0 */  obstack_grow (&notes, name, name_length);  preserved_copy_of_name = obstack_finish (&notes);  S_SET_NAME (symbolP, preserved_copy_of_name);  S_SET_SEGMENT (symbolP, segment);  S_SET_VALUE (symbolP, valu);  symbol_clear_list_pointers(symbolP);  symbol_set_frag (symbolP, frag);  /*   * Link to end of symbol chain.   */  {    extern int symbol_table_frozen;    if (symbol_table_frozen)      abort ();  }  symbol_append (symbolP, symbol_lastP, &symbol_rootP, &symbol_lastP);  obj_symbol_new_hook (symbolP);#ifdef tc_symbol_new_hook  tc_symbol_new_hook (symbolP);#endif#define DEBUG_SYMS#ifdef DEBUG_SYMS  verify_symbol_chain(symbol_rootP, symbol_lastP);#endif /* DEBUG_SYMS */}/* i370_addr_offset() will convert operand expressions * that appear to be absolute into thier base-register * relative form.  These expressions come in two types: * * (1) of the form "* + const" * where "*" means * relative offset since the last using * i.e. "*" means ".-using_baseaddr" * * (2) labels, which are never absolute, but are always * relative to the last "using".  Anything with an alpha * character is considered to be a label (since symbols * can never be operands), and since we've already handled * register operands. For example, "BL .L33" branch low * to .L33 RX form insn frequently terminates for-loops, */static booleani370_addr_offset (expressionS *exx){  char *dot, *lab;  int islabel = 0;  int all_digits = 0;  /* search for a label; anything with an alpha char will do */  /* local labels consist of N digits followed by either b or f */  lab = input_line_pointer;  while (*lab && (',' != *lab) && ('(' != *lab))    {      if (isdigit(*lab))	{	  all_digits = 1;	}      else if (isalpha(*lab))	{	  if (!all_digits)	    {	      islabel = 1;	      break;	    }	  else if (('f' == *lab) || ('b' == *lab))	    {	      islabel = 1;	      break;	    }	  if (all_digits)	    break;	}      else if ('.' != *lab)        break;      ++lab;    }  /* See if operand has a * in it */  dot = strchr (input_line_pointer, '*');  if (!dot && !islabel)    return false;  /* replace * with . and let expr munch on it.  */  if (dot)    *dot = '.';  expression (exx);  /* OK, now we have to subtract the "using" location  */  /* normally branches appear in the text section only...  */  if (0 == strncmp (now_seg->name, ".text", 5) || 0 > i370_using_other_regno)    {      i370_make_relative (exx, &i370_using_text_baseaddr);    }  else    {      i370_make_relative (exx, &i370_using_other_baseaddr);    }  /* put the * back */  if (dot)    *dot = '*';  return true;}/* handle address constants of various sorts *//* The currently supported types are *    =A(some_symb) *    =V(some_extern) *    =X'deadbeef'    hexadecimal *    =F'1234'        32-bit const int *    =H'1234'        16-bit const int */static booleani370_addr_cons (expressionS *exp){  char *name;  char *sym_name, delim;  int name_len;  int hex_len=0;  int cons_len=0;  name = input_line_pointer;  sym_name = input_line_pointer;  /* Find the spelling of the operand */  if (name[0] == '=' && isalpha (name[1]))    {      name = ++input_line_pointer;    }  else    {      return false;    }  switch (name[0])    {    case 'A':    case 'V':      /* A == address-of */      /* V == extern */      ++input_line_pointer;      expression (exp);      /* we use a simple string name to collapse together       * multiple refrences to the same address literal       */      name_len = strcspn (sym_name, ", ");      delim = *(sym_name + name_len);      *(sym_name + name_len) = 0x0;      add_to_lit_pool (exp, sym_name, 4);      *(sym_name + name_len) = delim;      break;    case 'H':    case 'F':    case 'X':    case 'E':  /* single-precision float point */    case 'D':  /* double-precision float point */      /* H == 16-bit fixed-point const; expression must be const */      /* F == fixed-point const; expression must be const */      /* X == fixed-point const; expression must be const */      if ('H' == name[0]) cons_len = 2;      else if ('F' == name[0]) cons_len = 4;      else if ('X' == name[0]) cons_len = -1;      else if ('E' == name[0]) cons_len = 4;      else if ('D' == name[0]) cons_len = 8;      /* extract length, if it is present; hack alert -- assume single-digit       * length */      if ('L' == name[1])	{	  cons_len = name[2] - '0';  /* should work for ascii and ebcdic */	  input_line_pointer += 2;	}      ++input_line_pointer;      /* get rid of pesky quotes */      if ('\'' == *input_line_pointer)	{	  char * close;	  ++input_line_pointer;	  close = strchr (input_line_pointer, '\'');	  if (close)	    *close= ' ';	  else	    as_bad ("missing end-quote");	}      if ('\"' == *input_line_pointer)	{	  char * close;	  ++input_line_pointer;	  close = strchr (input_line_pointer, '\"');	  if (close)	    *close= ' ';	  else	    as_bad ("missing end-quote");	}      if (('X' == name[0]) || ('E' == name[0]) || ('D' == name[0]))	{	  char tmp[50];	  char *save;	  /* The length of hex constants is specified directly with L,	   * or implied through the number of hex digits. For example:	   * =X'AB'       one byte	   * =X'abcd'     two bytes	   * =X'000000AB' four bytes	   * =XL4'AB'     four bytes, left-padded withn zero	   */	  if (('X' == name[0]) && (0 > cons_len))	    {	      save = input_line_pointer;	      while (*save)		{		  if (isxdigit(*save))		    hex_len++;		  save++;		}	      cons_len = (hex_len+1) /2;	    }	  /* I beleive this works even for =XL8'dada0000beeebaaa'	   * which should parse out to X_op == O_big	   * Note that floats and doubles get represented as	   * 0d3.14159265358979  or 0f 2.7	   */	  tmp[0] = '0';	  tmp[1] = name[0];	  tmp[2] = 0;	  strcat (tmp, input_line_pointer);	  save = input_line_pointer;	  input_line_pointer = tmp;	  expression (exp);	  input_line_pointer = save + (input_line_pointer-tmp-2);	  /* fix up lengths for floats and doubles */	  if (O_big == exp->X_op)	    {	      exp->X_add_number = cons_len / CHARS_PER_LITTLENUM;	    }	}      else	{	  expression (exp);	}      /* O_big occurs when more than 4 bytes worth gets parsed */      if ((exp->X_op != O_constant) && (exp->X_op != O_big))	{	  as_bad ("expression not a constant");	  return false;	}      add_to_lit_pool (exp, 0x0, cons_len);      break;    default:      as_bad ("Unknown/unsupported address literal type");      return false;    }  return true;}/* Dump the contents of the literal pool that we've accumulated so far. * This aligns the pool to the size of the largest literal in the pool. */static voidi370_ltorg (ignore)     int ignore;{  int litsize;  int lit_count = 0;  int biggest_literal_size = 0;  int biggest_align = 0;  char pool_name[20];  if (strncmp (now_seg->name, ".text", 5))    {      if (i370_other_section == undefined_section)        {          as_bad (".ltorg without prior .using in section %s",		  now_seg->name);        }      if (i370_other_section != now_seg)        {	  as_bad (".ltorg in section %s paired to .using in section %s",		  now_seg->name, i370_other_section->name);        }    }  if (! longlong_poolP      && ! word_poolP      && ! short_poolP      && ! byte_poolP)    {      /* Nothing to do */      /* as_tsktsk ("Nothing to put in the pool\n"); */      return;    }  /* find largest literal .. 2 4 or 8 */  lit_count = 0;  while (lit_count < next_literal_pool_place)    {      if (biggest_literal_size < literals[lit_count].size)	biggest_literal_size = literals[lit_count].size;      lit_count ++;    }  if (1 == biggest_literal_size) biggest_align = 0;  else if (2 == biggest_literal_size) biggest_align = 1;  else if (4 == biggest_literal_size) biggest_align = 2;  else if (8 == biggest_literal_size) biggest_align = 3;  else as_bad ("bad alignment of %d bytes in literal pool", biggest_literal_size);  if (0 == biggest_align) biggest_align = 1;  /* Align pool for short, word, double word accesses */  frag_align (biggest_align, 0, 0);  record_alignment (now_seg, biggest_align);  /* Note that the gas listing will print only the first five   * entries in the pool .... wonder how to make it print more ...   */  /* output largest literals first, then the smaller ones.  */  for (litsize=8; litsize; litsize /=2)    {      symbolS *current_poolP = NULL;      switch (litsize)	{	case 8:	  current_poolP = longlong_poolP; break;	case 4:	  current_poolP = word_poolP; break;	case 2:	  current_poolP = short_poolP; break;	case 1:	  current_poolP = byte_poolP; break;	default:	  as_bad ("bad literal size\n");	}      if (NULL == current_poolP)	continue;      sprintf (pool_name, ".LITP%01d%06d", litsize, lit_pool_num);      symbol_locate (current_poolP, pool_name, now_seg,		     (valueT) frag_now_fix (), frag_now);      symbol_table_insert (current_poolP);      lit_count = 0;      while (lit_count < next_literal_pool_place)	{	  if (litsize == literals[lit_count].size)	    {#define EMIT_ADDR_CONS_SYMBOLS#ifdef EMIT_ADDR_CONS_SYMBOLS	      /* create a bogus symbol, add it to the pool ...	       * For the most part, I think this is a useless excercise,	       * except that having these symbol names in the objects	       * is vaguely useful for debugging ...	       */	      if (literals[lit_count].sym_name)		{		  symbolS * symP = symbol_make_empty();		  symbol_locate (symP, literals[lit_count].sym_name, now_seg,				 (valueT) frag_now_fix (), frag_now);		  symbol_table_insert (symP);		}#endif /* EMIT_ADDR_CONS_SYMBOLS */	      emit_expr (&(literals[lit_count].exp), literals[lit_count].size);	    }	  lit_count ++;	}    }  next_literal_pool_place = 0;  longlong_poolP = NULL;  word_poolP = NULL;  short_poolP = NULL;  byte_poolP = NULL;  lit_pool_num++;}

⌨️ 快捷键说明

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