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

📄 tc-sparc.c

📁 基于4个mips核的noc设计
💻 C
📖 第 1 页 / 共 5 页
字号:
	      the_insn.reloc = BFD_RELOC_NONE; /* reloc handled elsewhere  */	      goto immediate;	    case 'l':		/* 22 bit PC relative immediate  */	      the_insn.reloc = BFD_RELOC_SPARC_WDISP22;	      the_insn.pcrel = 1;	      goto immediate;	    case 'L':		/* 30 bit immediate  */	      the_insn.reloc = BFD_RELOC_32_PCREL_S2;	      the_insn.pcrel = 1;	      goto immediate;	    case 'h':	    case 'n':		/* 22 bit immediate  */	      the_insn.reloc = BFD_RELOC_SPARC22;	      goto immediate;	    case 'i':		/* 13 bit immediate  */	      the_insn.reloc = BFD_RELOC_SPARC13;	      /* fallthrough */	    immediate:	      if (*s == ' ')		s++;	      {		char *s1;		char *op_arg = NULL;		expressionS op_exp;		bfd_reloc_code_real_type old_reloc = the_insn.reloc;		/* Check for %hi, etc.  */		if (*s == '%')		  {		    static const struct ops {		      /* The name as it appears in assembler.  */		      char *name;		      /* strlen (name), precomputed for speed */		      int len;		      /* The reloc this pseudo-op translates to.  */		      int reloc;		      /* Non-zero if for v9 only.  */		      int v9_p;		      /* Non-zero if can be used in pc-relative contexts.  */		      int pcrel_p;/*FIXME:wip*/		    } ops[] = {		      /* hix/lox must appear before hi/lo so %hix won't be			 mistaken for %hi.  */		      { "hix", 3, BFD_RELOC_SPARC_HIX22, 1, 0 },		      { "lox", 3, BFD_RELOC_SPARC_LOX10, 1, 0 },		      { "hi", 2, BFD_RELOC_HI22, 0, 1 },		      { "lo", 2, BFD_RELOC_LO10, 0, 1 },		      { "hh", 2, BFD_RELOC_SPARC_HH22, 1, 1 },		      { "hm", 2, BFD_RELOC_SPARC_HM10, 1, 1 },		      { "lm", 2, BFD_RELOC_SPARC_LM22, 1, 1 },		      { "h44", 3, BFD_RELOC_SPARC_H44, 1, 0 },		      { "m44", 3, BFD_RELOC_SPARC_M44, 1, 0 },		      { "l44", 3, BFD_RELOC_SPARC_L44, 1, 0 },		      { "uhi", 3, BFD_RELOC_SPARC_HH22, 1, 0 },		      { "ulo", 3, BFD_RELOC_SPARC_HM10, 1, 0 },		      { NULL, 0, 0, 0, 0 }		    };		    const struct ops *o;		    for (o = ops; o->name; o++)		      if (strncmp (s + 1, o->name, o->len) == 0)			break;		    if (o->name == NULL)		      break;		    if (s[o->len + 1] != '(')		      {			as_bad (_("Illegal operands: %%%s requires arguments in ()"), o->name);			return special_case;		      }		    op_arg = o->name;		    the_insn.reloc = o->reloc;		    s += o->len + 2;		    v9_arg_p = o->v9_p;		  }		/* Note that if the get_expression() fails, we will still		   have created U entries in the symbol table for the		   'symbols' in the input string.  Try not to create U		   symbols for registers, etc.  */		/* This stuff checks to see if the expression ends in		   +%reg.  If it does, it removes the register from		   the expression, and re-sets 's' to point to the		   right place.  */		if (op_arg)		  {		    int npar = 0;		    for (s1 = s; *s1 && *s1 != ',' && *s1 != ']'; s1++)		      if (*s1 == '(')			npar++;		      else if (*s1 == ')')			{			  if (!npar)			    break;			  npar--;			}		    if (*s1 != ')')		      {			as_bad (_("Illegal operands: %%%s requires arguments in ()"), op_arg);			return special_case;		      }		    *s1 = '\0';		    (void) get_expression (s);		    *s1 = ')';		    s = s1 + 1;		    if (*s == ',' || *s == ']' || !*s)		      continue;		    if (*s != '+' && *s != '-')		      {			as_bad (_("Illegal operands: Can't do arithmetics other than + and - involving %%%s()"), op_arg);			return special_case;		      }		    *s1 = '0';		    s = s1;		    op_exp = the_insn.exp;		    memset (&the_insn.exp, 0, sizeof (the_insn.exp));		  }		for (s1 = s; *s1 && *s1 != ',' && *s1 != ']'; s1++)		  ;		if (s1 != s && isdigit ((unsigned char) s1[-1]))		  {		    if (s1[-2] == '%' && s1[-3] == '+')		      s1 -= 3;		    else if (strchr ("goli0123456789", s1[-2]) && s1[-3] == '%' && s1[-4] == '+')		      s1 -= 4;		    else		      s1 = NULL;		    if (s1)		      {			*s1 = '\0';			if (op_arg && s1 == s + 1)			  the_insn.exp.X_op = O_absent;			else			  (void) get_expression (s);			*s1 = '+';			if (op_arg)			  *s = ')';			s = s1;		      }		  }		else		  s1 = NULL;		if (!s1)		  {		    (void) get_expression (s);		    if (op_arg)		      *s = ')';		    s = expr_end;		  }		if (op_arg)		  {		    the_insn.exp2 = the_insn.exp;		    the_insn.exp = op_exp;		    if (the_insn.exp2.X_op == O_absent)		      the_insn.exp2.X_op = O_illegal;		    else if (the_insn.exp.X_op == O_absent)		      {			the_insn.exp = the_insn.exp2;			the_insn.exp2.X_op = O_illegal;		      }		    else if (the_insn.exp.X_op == O_constant)		      {			valueT val = the_insn.exp.X_add_number;			switch (the_insn.reloc)			  {			  default:			    break;			  case BFD_RELOC_SPARC_HH22:			    val = BSR (val, 32);			    /* Fall through.  */			  case BFD_RELOC_SPARC_LM22:			  case BFD_RELOC_HI22:			    val = (val >> 10) & 0x3fffff;			    break;			  case BFD_RELOC_SPARC_HM10:			    val = BSR (val, 32);			    /* Fall through.  */			  case BFD_RELOC_LO10:			    val &= 0x3ff;			    break;			  case BFD_RELOC_SPARC_H44:			    val >>= 22;			    val &= 0x3fffff;			    break;			  case BFD_RELOC_SPARC_M44:			    val >>= 12;			    val &= 0x3ff;			    break;			  case BFD_RELOC_SPARC_L44:			    val &= 0xfff;			    break;			  case BFD_RELOC_SPARC_HIX22:			    val = ~val;			    val = (val >> 10) & 0x3fffff;			    break;			  case BFD_RELOC_SPARC_LOX10:			    val = (val & 0x3ff) | 0x1c00;			    break;			  }			the_insn.exp = the_insn.exp2;			the_insn.exp.X_add_number += val;			the_insn.exp2.X_op = O_illegal;			the_insn.reloc = old_reloc;		      }		    else if (the_insn.exp2.X_op != O_constant)		      {			as_bad (_("Illegal operands: Can't add non-constant expression to %%%s()"), op_arg);			return special_case;		      }		    else		      {			if (old_reloc != BFD_RELOC_SPARC13			    || the_insn.reloc != BFD_RELOC_LO10			    || sparc_arch_size != 64			    || sparc_pic_code)			  {			    as_bad (_("Illegal operands: Can't do arithmetics involving %%%s() of a relocatable symbol"), op_arg);			    return special_case;			  }			the_insn.reloc = BFD_RELOC_SPARC_OLO10;		      }		  }	      }	      /* Check for constants that don't require emitting a reloc.  */	      if (the_insn.exp.X_op == O_constant		  && the_insn.exp.X_add_symbol == 0		  && the_insn.exp.X_op_symbol == 0)		{		  /* For pc-relative call instructions, we reject		     constants to get better code.  */		  if (the_insn.pcrel		      && the_insn.reloc == BFD_RELOC_32_PCREL_S2		      && in_signed_range (the_insn.exp.X_add_number, 0x3fff))		    {		      error_message = _(": PC-relative operand can't be a constant");		      goto error;		    }		  /* Constants that won't fit are checked in md_apply_fix3		     and bfd_install_relocation.		     ??? It would be preferable to install the constants		     into the insn here and save having to create a fixS		     for each one.  There already exists code to handle		     all the various cases (e.g. in md_apply_fix3 and		     bfd_install_relocation) so duplicating all that code		     here isn't right.  */		}	      continue;	    case 'a':	      if (*s++ == 'a')		{		  opcode |= ANNUL;		  continue;		}	      break;	    case 'A':	      {		int asi = 0;		/* Parse an asi.  */		if (*s == '#')		  {		    if (! parse_keyword_arg (sparc_encode_asi, &s, &asi))		      {			error_message = _(": invalid ASI name");			goto error;		      }		  }		else		  {		    if (! parse_const_expr_arg (&s, &asi))		      {			error_message = _(": invalid ASI expression");			goto error;		      }		    if (asi < 0 || asi > 255)		      {			error_message = _(": invalid ASI number");			goto error;		      }		  }		opcode |= ASI (asi);		continue;	      }			/* Alternate space.  */	    case 'p':	      if (strncmp (s, "%psr", 4) == 0)		{		  s += 4;		  continue;		}	      break;	    case 'q':		/* Floating point queue.  */	      if (strncmp (s, "%fq", 3) == 0)		{		  s += 3;		  continue;		}	      break;	    case 'Q':		/* Coprocessor queue.  */	      if (strncmp (s, "%cq", 3) == 0)		{		  s += 3;		  continue;		}	      break;	    case 'S':	      if (strcmp (str, "set") == 0		  || strcmp (str, "setuw") == 0)		{		  special_case = SPECIAL_CASE_SET;		  continue;		}	      else if (strcmp (str, "setsw") == 0)		{		  special_case = SPECIAL_CASE_SETSW;		  continue;		}	      else if (strcmp (str, "setx") == 0)		{		  special_case = SPECIAL_CASE_SETX;		  continue;		}	      else if (strncmp (str, "fdiv", 4) == 0)		{		  special_case = SPECIAL_CASE_FDIV;		  continue;		}	      break;	    case 'o':	      if (strncmp (s, "%asi", 4) != 0)		break;	      s += 4;	      continue;	    case 's':	      if (strncmp (s, "%fprs", 5) != 0)		break;	      s += 5;	      continue;	    case 'E':	      if (strncmp (s, "%ccr", 4) != 0)		break;	      s += 4;	      continue;	    case 't':	      if (strncmp (s, "%tbr", 4) != 0)		break;	      s += 4;	      continue;	    case 'w':	      if (strncmp (s, "%wim", 4) != 0)		break;	      s += 4;	      continue;	    case 'x':	      {		char *push = input_line_pointer;		expressionS e;		input_line_pointer = s;		expression (&e);		if (e.X_op == O_constant)		  {		    int n = e.X_add_number;		    if (n != e.X_add_number || (n & ~0x1ff) != 0)		      as_bad (_("OPF immediate operand out of range (0-0x1ff)"));		    else		      opcode |= e.X_add_number << 5;		  }		else		  as_bad (_("non-immediate OPF operand, ignored"));		s = input_line_pointer;		input_line_pointer = push;		continue;	      }	    case 'y':	      if (strncmp (s, "%y", 2) != 0)		break;	      s += 2;	      continue;	    case 'u':	    case 'U':	      {		/* Parse a sparclet cpreg.  */		int cpreg;		if (! parse_keyword_arg (sparc_encode_sparclet_cpreg, &s, &cpreg))		  {		    error_message = _(": invalid cpreg name");		    goto error;		  }		opcode |= (*args == 'U' ? RS1 (cpreg) : RD (cpreg));		continue;	      }	    default:	      as_fatal (_("failed sanity check."));	    }			/* switch on arg code.  */	  /* Break out of for() loop.  */	  break;	}			/* For each arg that we expect.  */    error:      if (match == 0)	{	  /* Args don't match.  */	  if (&insn[1] - sparc_opcodes < sparc_num_opcodes	      && (insn->name == insn[1].name		  || !strcmp (insn->name, insn[1].name)))	    {	      ++insn;	      s = argsStart;	      continue;	    }	  else	    {	      as_bad (_("Illegal operands%s"), error_message);	      return special_case;	    }	}      else	{	  /* We have a match.  Now see if the architecture is OK.  */	  int needed_arch_mask = insn->architecture;	  if (v9_arg_p)	    {	      needed_arch_mask &=		~(SPARC_OPCODE_ARCH_MASK (SPARC_OPCODE_ARCH_V9) - 1);	      if (! needed_arch_mask)		needed_arch_mask =		  SPARC_OPCODE_ARCH_MASK (SPARC_OPCODE_ARCH_V9);	    }	  if (needed_arch_mask	      & SPARC_OPCODE_SUPPORTED (current_architecture))	    /* OK.  */	    ;	  /* Can we bump up the architecture?  */	  else if (needed_arch_mask		   & SPARC_OPCODE_SUPPORTED (max_architecture))	    {	      enum sparc_opcode_arch_val needed_architecture =		sparc_ffs (SPARC_OPCODE_SUPPORTED (max_architecture)			   & needed_arch_mask);	      assert (needed_architecture <= SPARC_OPCODE_ARCH_MAX);	      if (warn_on_bump		  && needed_architecture > warn_after_architecture)		{		  as_warn (_("architecture bumped from \"%s\" to \"%s\" on \"%s\""),			   sparc_opcode_archs[current_architecture].name,			   sparc_opcode_archs[needed_architecture].name,			   str);		  warn_after_architecture = needed_architecture;		}	      current_architecture = needed_architecture;	    }	  /* Conflict.  */	  /* ??? This seems to be a bit fragile.  What if the next entry in	     the opcode table is the one we want and it is supported?	     It is possible to arrange the table today so that this can't	     happen but what about tomorrow?  */	  else	    {	      int arch, printed_one_p = 0;	      char *p;	      char required_archs[SPARC_OPCODE_ARCH_MAX * 16];	      /* Create a list of the architectures that support the insn.  */	      needed_arch_mask &= ~SPARC_OPCODE_SUPPORTED (max_architecture);	      p = required_archs;	      arch = sparc_ffs (needed_arch_mask);	      while ((1 << arch) <= needed_arch_mask)		{		  if ((1 << arch) & needed_arch_mask)		    {		      if (printed_one_p)			*p++ = '|';		      strcpy (p, sparc_opcode_archs[arch].name);		      p += strlen (p);		      printed_one_p = 1;		    }		  ++arch;		}	      as_bad (_("Architecture mismatch o

⌨️ 快捷键说明

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