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

📄 tc-arc.c

📁 基于4个mips核的noc设计
💻 C
📖 第 1 页 / 共 4 页
字号:
		 just go on to try the next one.  */	      if (*str == ' ')		{		  ++syn;		  continue;		}	      s = str;	      if (mods & ARC_MOD_DOT)		{		  if (*s != '.')		    break;		  ++s;		}	      else		{		  /* This can happen in "b.nd foo" and we're currently looking		     for "%q" (ie: a condition code suffix).  */		  if (*s == '.')		    {		      ++syn;		      continue;		    }		}	      /* Pick the suffix out and look it up via the hash table.  */	      for (t = s; *t && isalnum (*t); ++t)		continue;	      c = *t;	      *t = '\0';	      if ((suf = get_ext_suffix (s)))		ext_suffix_p = 1;	      else		suf = hash_find (arc_suffix_hash, s);	      if (!suf)		{		  /* This can happen in "blle foo" and we're currently using		     the template "b%q%.n %j".  The "bl" insn occurs later in		     the table so "lle" isn't an illegal suffix.  */		  *t = c;		  break;		}	      /* Is it the right type?  Note that the same character is used		 several times, so we have to examine all of them.  This is		 relatively efficient as equivalent entries are kept		 together.  If it's not the right type, don't increment `str'		 so we try the next one in the series.  */	      found = 0;	      if (ext_suffix_p && arc_operands[suf->type].fmt == *syn)		{		  /* Insert the suffix's value into the insn.  */		  *t = c;		  if (operand->insert)		    insn = (*operand->insert) (insn, operand,					       mods, NULL, suf->value,					       NULL);		  else		    insn |= suf->value << operand->shift;		  str = t;		  found = 1;		}	      else		{		  *t = c;		  suffix_end = arc_suffixes + arc_suffixes_count;		  for (suffix = suf;		       suffix < suffix_end && strcmp (suffix->name, suf->name) == 0;		       ++suffix)		    {		      if (arc_operands[suffix->type].fmt == *syn)			{			  /* Insert the suffix's value into the insn.  */			  if (operand->insert)			    insn = (*operand->insert) (insn, operand,						       mods, NULL, suffix->value,						       NULL);			  else			    insn |= suffix->value << operand->shift;			  str = t;			  found = 1;			  break;			}		    }		}	      ++syn;	      if (!found)		/* Wrong type.  Just go on to try next insn entry.  */		;	      else		{		  if (num_suffixes == MAX_SUFFIXES)		    as_bad ("too many suffixes");		  else		    insn_suffixes[num_suffixes++] = suffix;		}	    }	  else	    /* This is either a register or an expression of some kind.  */	    {	      char *hold;	      const struct arc_operand_value *reg = NULL;	      long value = 0;	      expressionS exp;	      if (operand->flags & ARC_OPERAND_SUFFIX)		abort ();	      /* Is there anything left to parse?		 We don't check for this at the top because we want to parse		 any trailing fake arguments in the syntax string.  */	      if (is_end_of_line[(unsigned char) *str])		break;	      /* Parse the operand.  */	      hold = input_line_pointer;	      input_line_pointer = str;	      expression (&exp);	      str = input_line_pointer;	      input_line_pointer = hold;	      if (exp.X_op == O_illegal)		as_bad ("illegal operand");	      else if (exp.X_op == O_absent)		as_bad ("missing operand");	      else if (exp.X_op == O_constant)		{		  value = exp.X_add_number;		}	      else if (exp.X_op == O_register)		{		  reg = (struct arc_operand_value *) exp.X_add_number;		}#define IS_REG_DEST_OPERAND(o) ((o) == 'a')	      else if (IS_REG_DEST_OPERAND (*syn))		as_bad ("symbol as destination register");	      else		{		  if (!strncmp (str, "@h30", 4))		    {		      arc_code_symbol (&exp);		      str += 4;		    }		  /* We need to generate a fixup for this expression.  */		  if (fc >= MAX_FIXUPS)		    as_fatal ("too many fixups");		  fixups[fc].exp = exp;		  /* We don't support shimm relocs. break here to force		     the assembler to output a limm.  */#define IS_REG_SHIMM_OFFSET(o) ((o) == 'd')		  if (IS_REG_SHIMM_OFFSET (*syn))		    break;		  /* If this is a register constant (IE: one whose		     register value gets stored as 61-63) then this		     must be a limm.  */		  /* ??? This bit could use some cleaning up.		     Referencing the format chars like this goes		     against style.  */		  if (IS_SYMBOL_OPERAND (*syn))		    {		      const char *junk;		      limm_reloc_p = 1;		      /* Save this, we don't yet know what reloc to use.  */		      fix_up_at = fc;		      /* Tell insert_reg we need a limm.  This is			 needed because the value at this point is			 zero, a shimm.  */		      /* ??? We need a cleaner interface than this.  */		      (*arc_operands[arc_operand_map['Q']].insert)			(insn, operand, mods, reg, 0L, &junk);		    }		  else		    fixups[fc].opindex = arc_operand_map[(int) *syn];		  ++fc;		  value = 0;		}	      /* Insert the register or expression into the instruction.  */	      if (operand->insert)		{		  const char *errmsg = NULL;		  insn = (*operand->insert) (insn, operand, mods,					     reg, (long) value, &errmsg);		  if (errmsg != (const char *) NULL)		    {		      last_errmsg = errmsg;		      if (operand->flags & ARC_OPERAND_ERROR)			{			  as_bad (errmsg);			  return;			}		      else if (operand->flags & ARC_OPERAND_WARN)			as_warn (errmsg);		      break;		    }		}	      else		insn |= (value & ((1 << operand->bits) - 1)) << operand->shift;	      ++syn;	    }	}      /* If we're at the end of the syntax string, we're done.  */      /* FIXME: try to move this to a separate function.  */      if (*syn == '\0')	{	  int i;	  char *f;	  long limm, limm_p;	  /* For the moment we assume a valid `str' can only contain blanks	     now.  IE: We needn't try again with a longer version of the	     insn and it is assumed that longer versions of insns appear	     before shorter ones (eg: lsr r2,r3,1 vs lsr r2,r3).  */	  while (isspace (*str))	    ++str;	  if (!is_end_of_line[(unsigned char) *str])	    as_bad ("junk at end of line: `%s'", str);	  /* Is there a limm value?  */	  limm_p = arc_opcode_limm_p (&limm);	  /* Perform various error and warning tests.  */	  {	    static int in_delay_slot_p = 0;	    static int prev_insn_needs_cc_nop_p = 0;	    /* delay slot type seen */	    int delay_slot_type = ARC_DELAY_NONE;	    /* conditional execution flag seen */	    int conditional = 0;	    /* 1 if condition codes are being set */	    int cc_set_p = 0;	    /* 1 if conditional branch, including `b' "branch always" */	    int cond_branch_p = opcode->flags & ARC_OPCODE_COND_BRANCH;	    for (i = 0; i < num_suffixes; ++i)	      {		switch (arc_operands[insn_suffixes[i]->type].fmt)		  {		  case 'n':		    delay_slot_type = insn_suffixes[i]->value;		    break;		  case 'q':		    conditional = insn_suffixes[i]->value;		    break;		  case 'f':		    cc_set_p = 1;		    break;		  }	      }	    /* Putting an insn with a limm value in a delay slot is supposed to	       be legal, but let's warn the user anyway.  Ditto for 8 byte	       jumps with delay slots.  */	    if (in_delay_slot_p && limm_p)	      as_warn ("8 byte instruction in delay slot");	    if (delay_slot_type != ARC_DELAY_NONE		&& limm_p && arc_insn_not_jl (insn)) /* except for jl  addr */	      as_warn ("8 byte jump instruction with delay slot");	    in_delay_slot_p = (delay_slot_type != ARC_DELAY_NONE) && !limm_p;	    /* Warn when a conditional branch immediately follows a set of	       the condition codes.  Note that this needn't be done if the	       insn that sets the condition codes uses a limm.  */	    if (cond_branch_p && conditional != 0 /* 0 = "always" */		&& prev_insn_needs_cc_nop_p && arc_mach_type == bfd_mach_arc_5)	      as_warn ("conditional branch follows set of flags");	    prev_insn_needs_cc_nop_p =	      /* FIXME: ??? not required:		 (delay_slot_type != ARC_DELAY_NONE) &&  */	      cc_set_p && !limm_p;	  }	  /* Write out the instruction.	     It is important to fetch enough space in one call to `frag_more'.	     We use (f - frag_now->fr_literal) to compute where we are and we	     don't want frag_now to change between calls.  */	  if (limm_p)	    {	      f = frag_more (8);	      md_number_to_chars (f, insn, 4);	      md_number_to_chars (f + 4, limm, 4);	      dwarf2_emit_insn (8);	    }	  else if (limm_reloc_p)	    {	      /* We need a limm reloc, but the tables think we don't.  */	      abort ();	    }	  else	    {	      f = frag_more (4);	      md_number_to_chars (f, insn, 4);	      dwarf2_emit_insn (4);	    }	  /* Create any fixups.  */	  for (i = 0; i < fc; ++i)	    {	      int op_type, reloc_type;	      expressionS exptmp;	      const struct arc_operand *operand;	      /* Create a fixup for this operand.		 At this point we do not use a bfd_reloc_code_real_type for		 operands residing in the insn, but instead just use the		 operand index.  This lets us easily handle fixups for any		 operand type, although that is admittedly not a very exciting		 feature.  We pick a BFD reloc type in md_apply_fix.		 Limm values (4 byte immediate "constants") must be treated		 normally because they're not part of the actual insn word		 and thus the insertion routines don't handle them.  */	      if (arc_operands[fixups[i].opindex].flags & ARC_OPERAND_LIMM)		{		  /* Modify the fixup addend as required by the cpu.  */		  fixups[i].exp.X_add_number += arc_limm_fixup_adjust (insn);		  op_type = fixups[i].opindex;		  /* FIXME: can we add this data to the operand table?  */		  if (op_type == arc_operand_map['L']		      || op_type == arc_operand_map['s']		      || op_type == arc_operand_map['o']		      || op_type == arc_operand_map['O'])		    reloc_type = BFD_RELOC_32;		  else if (op_type == arc_operand_map['J'])		    reloc_type = BFD_RELOC_ARC_B26;		  else		    abort ();		  reloc_type = get_arc_exp_reloc_type (1, reloc_type,						       &fixups[i].exp,						       &exptmp);		}	      else		{		  op_type = get_arc_exp_reloc_type (0, fixups[i].opindex,						    &fixups[i].exp, &exptmp);		  reloc_type = op_type + (int) BFD_RELOC_UNUSED;		}	      operand = &arc_operands[op_type];	      fix_new_exp (frag_now,			   ((f - frag_now->fr_literal)			    + (operand->flags & ARC_OPERAND_LIMM ? 4 : 0)), 4,			   &exptmp,			   (operand->flags & ARC_OPERAND_RELATIVE_BRANCH) != 0,			   (bfd_reloc_code_real_type) reloc_type);	    }	  /* All done.  */	  return;	}      /* Try the next entry.  */    }  if (NULL == last_errmsg)    as_bad ("bad instruction `%s'", start);  else    as_bad (last_errmsg);}static voidarc_extoper (opertype)     int opertype;{  char *name;  char *mode;  char c;  char *p;  int imode = 0;  int number;  struct arc_ext_operand_value *ext_oper;  symbolS *symbolP;  segT old_sec;  int old_subsec;  name = input_line_pointer;  c = get_symbol_end ();  name = xstrdup (name);  if (NULL == name)    {      ignore_rest_of_line ();      return;    }  p = name;  while (*p)    {      if (isupper (*p))	*p = tolower (*p);      p++;    }  /* just after name is now '\0'  */  p = input_line_pointer;  *p = c;  SKIP_WHITESPACE ();  if (*input_line_pointer != ',')    {      as_bad ("expected comma after operand name");      ignore_rest_of_line ();      free (name);      return;    }  input_line_pointer++;		/* skip ','  */  number = get_absolute_expression ();  if (number < 0)    {      as_bad ("negative operand number %d", number);      ignore_rest_of_line ();      free (name);      return;    }  if (opertype)    {      SKIP_WHITESPACE ();      if (*input_line_pointer != ',')	{	  as_bad ("expected comma after register-number");	  ignore_rest_of_line ();	  free (name);	  return;	}      input_line_pointer++;		/* skip ','  */      mode = input_line_pointer;      if (!strncmp (mode, "r|w", 3))	{	  imode = 0;	  input_line_pointer += 3;	}      else	{	  if (!strncmp (mode, "r", 1))	    {	      imode = ARC_REGISTER_READONLY;	      input_line_pointer += 1;	    }	  else	    {	      if (strncmp (mode, "w", 1))		{		  as_bad ("invalid mode");		  ignore_rest_of_line ();		  free (name);		  return;		}	      else		{		  imode = ARC_REGISTER_WRITEONLY;		  input_line_pointer += 1;		}	    }	}      SKIP_WHITESPACE ();      if (1 == opertype)	{	  if (*input_line_pointer != ',')	    {	      as_bad ("expected comma after register-mode");	      ignore_rest_of_line ();	      free (name);	      return;	    }	  input_line_pointer++;		/* skip ','  */	  if (!strncmp (input_line_pointer, "cannot_shortcut", 15))	    {	      imode |= arc_get_noshortcut_flag ();	      input_line_pointer += 15;	    }	  else	    {	      if (strncmp (input_line_pointer, "can_shortcut", 12))		{		  as_bad ("shortcut designator invalid");		  ignore_rest_of_line ();		  free (name);		  return;		}	      else		{		  input_line_pointer += 12;		}	    }	}    }  if ((opertype == 1) && number > 60)    {      as_bad ("core register value (%d) too large", number);      ignore_rest_of_line ();      free (name);      return;    }  if ((opertype == 0) && number > 31)    {      as_bad ("condition code value (%d) too large", number);      ignore_rest_of_line ();      free (name);      return;    }  ext_oper = (struct arc_ext_operand_value *) \    xmalloc (sizeof (struct arc_ext_operand_value));

⌨️ 快捷键说明

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