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

📄 tc-mn10200.c

📁 基于4个mips核的noc设计
💻 C
📖 第 1 页 / 共 3 页
字号:
	    case O_illegal:	      errmsg = _("illegal operand");	      goto error;	    case O_absent:	      errmsg = _("missing operand");	      goto error;	    case O_register:	      if ((operand->flags		   & (MN10200_OPERAND_DREG | MN10200_OPERAND_AREG)) == 0)		{		  input_line_pointer = hold;		  str = hold;		  goto error;		}	      if (opcode->format == FMT_2 || opcode->format == FMT_5)		extra_shift = 8;	      else if (opcode->format == FMT_3 || opcode->format == FMT_6		       || opcode->format == FMT_7)		extra_shift = 16;	      else		extra_shift = 0;	      mn10200_insert_operand (&insn, &extension, operand,				      ex.X_add_number, (char *) NULL,				      0, extra_shift);	      break;	    case O_constant:	      /* If this operand can be promoted, and it doesn't		 fit into the allocated bitfield for this insn,		 then promote it (ie this opcode does not match).  */	      if (operand->flags		  & (MN10200_OPERAND_PROMOTE | MN10200_OPERAND_RELAX)		  && !check_operand (insn, operand, ex.X_add_number))		{		  input_line_pointer = hold;		  str = hold;		  goto error;		}	      mn10200_insert_operand (&insn, &extension, operand,				      ex.X_add_number, (char *) NULL,				      0, 0);	      break;	    default:	      /* If this operand can be promoted, then this opcode didn't		 match since we can't know if it needed promotion!  */	      if (operand->flags & MN10200_OPERAND_PROMOTE)		{		  input_line_pointer = hold;		  str = hold;		  goto error;		}	      /* We need to generate a fixup for this expression.  */	      if (fc >= MAX_INSN_FIXUPS)		as_fatal (_("too many fixups"));	      fixups[fc].exp = ex;	      fixups[fc].opindex = *opindex_ptr;	      fixups[fc].reloc = BFD_RELOC_UNUSED;	      ++fc;	      break;	    }keep_going:	  str = input_line_pointer;	  input_line_pointer = hold;	  while (*str == ' ' || *str == ',')	    ++str;	}      /* Make sure we used all the operands!  */      if (*str != ',')	match = 1;    error:      if (match == 0)	{	  next_opcode = opcode + 1;	  if (!strcmp (next_opcode->name, opcode->name))	    {	      opcode = next_opcode;	      continue;	    }	  as_bad ("%s", errmsg);	  return;	}      break;    }  while (isspace (*str))    ++str;  if (*str != '\0')    as_bad (_("junk at end of line: `%s'"), str);  input_line_pointer = str;  if (opcode->format == FMT_1)    size = 1;  else if (opcode->format == FMT_2 || opcode->format == FMT_4)    size = 2;  else if (opcode->format == FMT_3 || opcode->format == FMT_5)    size = 3;  else if (opcode->format == FMT_6)    size = 4;  else if (opcode->format == FMT_7)    size = 5;  else    abort ();  /* Write out the instruction.  */  if (relaxable && fc > 0)    {      int type;      /* bCC  */      if (size == 2 && opcode->opcode != 0xfc0000)	{	  /* Handle bra specially.  Basically treat it like jmp so	     that we automatically handle 8, 16 and 32 bit offsets	     correctly as well as jumps to an undefined address.	     It is also important to not treat it like other bCC	     instructions since the long forms of bra is different	     from other bCC instructions.  */	  if (opcode->opcode == 0xea00)	    type = 8;	  else	    type = 0;	}      /* jsr  */      else if (size == 3 && opcode->opcode == 0xfd0000)	type = 6;      /* jmp  */      else if (size == 3 && opcode->opcode == 0xfc0000)	type = 8;      /* bCCx  */      else	type = 3;      f = frag_var (rs_machine_dependent, 8, 8 - size, type,		    fixups[0].exp.X_add_symbol,		    fixups[0].exp.X_add_number,		    (char *)fixups[0].opindex);      number_to_chars_bigendian (f, insn, size);      if (8 - size > 4)	{	  number_to_chars_bigendian (f + size, 0, 4);	  number_to_chars_bigendian (f + size + 4, 0, 8 - size - 4);	}      else	number_to_chars_bigendian (f + size, 0, 8 - size);    }  else    {      f = frag_more (size);      /* Oh, what a mess.  The instruction is in big endian format, but	 16 and 24bit immediates are little endian!  */      if (opcode->format == FMT_3)	{	  number_to_chars_bigendian (f, (insn >> 16) & 0xff, 1);	  number_to_chars_littleendian (f + 1, insn & 0xffff, 2);	}      else if (opcode->format == FMT_6)	{	  number_to_chars_bigendian (f, (insn >> 16) & 0xffff, 2);	  number_to_chars_littleendian (f + 2, insn & 0xffff, 2);	}      else if (opcode->format == FMT_7)	{	  number_to_chars_bigendian (f, (insn >> 16) & 0xffff, 2);	  number_to_chars_littleendian (f + 2, insn & 0xffff, 2);	  number_to_chars_littleendian (f + 4, extension & 0xff, 1);	}      else	{	  number_to_chars_bigendian (f, insn, size > 4 ? 4 : size);	}      /* Create any fixups.  */      for (i = 0; i < fc; i++)	{	  const struct mn10200_operand *operand;	  operand = &mn10200_operands[fixups[i].opindex];	  if (fixups[i].reloc != BFD_RELOC_UNUSED)	    {	      reloc_howto_type *reloc_howto;	      int size;	      int offset;	      fixS *fixP;	      reloc_howto = bfd_reloc_type_lookup (stdoutput,						   fixups[i].reloc);	      if (!reloc_howto)		abort ();	      size = bfd_get_reloc_size (reloc_howto);	      if (size < 1 || size > 4)		abort ();	      offset = 4 - size;	      fixP = fix_new_exp (frag_now, f - frag_now->fr_literal + offset,				  size,				  &fixups[i].exp,				  reloc_howto->pc_relative,				  fixups[i].reloc);	      /* PC-relative offsets are from the first byte of the		 next instruction, not from the start of the current		 instruction.  */	      if (reloc_howto->pc_relative)		fixP->fx_offset += size;	    }	  else	    {	      int reloc, pcrel, reloc_size, offset;	      fixS *fixP;	      reloc = BFD_RELOC_NONE;	      /* How big is the reloc?  Remember SPLIT relocs are		 implicitly 32bits.  */	      reloc_size = operand->bits;	      offset = size - reloc_size / 8;	      /* Is the reloc pc-relative?  */	      pcrel = (operand->flags & MN10200_OPERAND_PCREL) != 0;	      /* Choose a proper BFD relocation type.  */	      if (pcrel)		{		  if (reloc_size == 8)		    reloc = BFD_RELOC_8_PCREL;		  else if (reloc_size == 24)		    reloc = BFD_RELOC_24_PCREL;		  else		    abort ();		}	      else		{		  if (reloc_size == 32)		    reloc = BFD_RELOC_32;		  else if (reloc_size == 16)		    reloc = BFD_RELOC_16;		  else if (reloc_size == 8)		    reloc = BFD_RELOC_8;		  else if (reloc_size == 24)		    reloc = BFD_RELOC_24;		  else		    abort ();		}	      /* Convert the size of the reloc into what fix_new_exp                 wants.  */	      reloc_size = reloc_size / 8;	      if (reloc_size == 8)		reloc_size = 0;	      else if (reloc_size == 16)		reloc_size = 1;	      else if (reloc_size == 32 || reloc_size == 24)		reloc_size = 2;	      fixP = fix_new_exp (frag_now, f - frag_now->fr_literal + offset,				  reloc_size, &fixups[i].exp, pcrel,				  ((bfd_reloc_code_real_type) reloc));	      /* PC-relative offsets are from the first byte of the		 next instruction, not from the start of the current		 instruction.  */	      if (pcrel)		fixP->fx_offset += size;	    }	}    }}/* If while processing a fixup, a reloc really needs to be created   Then it is done here.  */arelent *tc_gen_reloc (seg, fixp)     asection *seg;     fixS *fixp;{  arelent *reloc;  reloc = (arelent *) xmalloc (sizeof (arelent));  reloc->howto = bfd_reloc_type_lookup (stdoutput, fixp->fx_r_type);  if (reloc->howto == (reloc_howto_type *) NULL)    {      as_bad_where (fixp->fx_file, fixp->fx_line,		    _("reloc %d not supported by object file format"),		    (int) fixp->fx_r_type);      return NULL;    }  reloc->address = fixp->fx_frag->fr_address + fixp->fx_where;  if (fixp->fx_addsy && fixp->fx_subsy)    {      if ((S_GET_SEGMENT (fixp->fx_addsy) != S_GET_SEGMENT (fixp->fx_subsy))	  || S_GET_SEGMENT (fixp->fx_addsy) == undefined_section)	{	  as_bad_where (fixp->fx_file, fixp->fx_line,			"Difference of symbols in different sections is not supported");	  return NULL;	}      reloc->sym_ptr_ptr = &bfd_abs_symbol;      reloc->addend = (S_GET_VALUE (fixp->fx_addsy)		       - S_GET_VALUE (fixp->fx_subsy) + fixp->fx_offset);    }  else    {      reloc->sym_ptr_ptr = (asymbol **) xmalloc (sizeof (asymbol *));      *reloc->sym_ptr_ptr = symbol_get_bfdsym (fixp->fx_addsy);      reloc->addend = fixp->fx_offset;    }  return reloc;}intmd_estimate_size_before_relax (fragp, seg)     fragS *fragp;     asection *seg;{  if (fragp->fr_subtype == 6      && (!S_IS_DEFINED (fragp->fr_symbol)	  || seg != S_GET_SEGMENT (fragp->fr_symbol)))    fragp->fr_subtype = 7;  else if (fragp->fr_subtype == 8	   && (!S_IS_DEFINED (fragp->fr_symbol)	       || seg != S_GET_SEGMENT (fragp->fr_symbol)))    fragp->fr_subtype = 10;  if (fragp->fr_subtype >= sizeof (md_relax_table) / sizeof (md_relax_table[0]))    abort ();  return md_relax_table[fragp->fr_subtype].rlx_length;}longmd_pcrel_from (fixp)     fixS *fixp;{  return fixp->fx_frag->fr_address;#if 0  if (fixp->fx_addsy != (symbolS *) NULL && !S_IS_DEFINED (fixp->fx_addsy))    {      /* The symbol is undefined.  Let the linker figure it out.  */      return 0;    }  return fixp->fx_frag->fr_address + fixp->fx_where;#endif}intmd_apply_fix3 (fixp, valuep, seg)     fixS *fixp;     valueT *valuep;     segT seg;{  /* We shouldn't ever get here because linkrelax is nonzero.  */  abort ();  fixp->fx_done = 1;  return 0;}/* Insert an operand value into an instruction.  */static voidmn10200_insert_operand (insnp, extensionp, operand, val, file, line, shift)     unsigned long *insnp;     unsigned long *extensionp;     const struct mn10200_operand *operand;     offsetT val;     char *file;     unsigned int line;     unsigned int shift;{  /* No need to check 24 or 32bit operands for a bit.  */  if (operand->bits < 24      && (operand->flags & MN10200_OPERAND_NOCHECK) == 0)    {      long min, max;      offsetT test;      if ((operand->flags & MN10200_OPERAND_SIGNED) != 0)	{	  max = (1 << (operand->bits - 1)) - 1;	  min = - (1 << (operand->bits - 1));	}      else	{	  max = (1 << operand->bits) - 1;	  min = 0;	}      test = val;      if (test < (offsetT) min || test > (offsetT) max)        {          const char *err =            _("operand out of range (%s not between %ld and %ld)");          char buf[100];          sprint_value (buf, test);          if (file == (char *) NULL)            as_warn (err, buf, min, max);          else            as_warn_where (file, line, err, buf, min, max);        }    }  if ((operand->flags & MN10200_OPERAND_EXTENDED) == 0)    {      *insnp |= (((long) val & ((1 << operand->bits) - 1))		 << (operand->shift + shift));      if ((operand->flags & MN10200_OPERAND_REPEATED) != 0)	*insnp |= (((long) val & ((1 << operand->bits) - 1))		   << (operand->shift + shift + 2));    }  else    {      *extensionp |= (val >> 16) & 0xff;      *insnp |= val & 0xffff;    }}static unsigned longcheck_operand (insn, operand, val)     unsigned long insn;     const struct mn10200_operand *operand;     offsetT val;{  /* No need to check 24bit or 32bit operands for a bit.  */  if (operand->bits < 24      && (operand->flags & MN10200_OPERAND_NOCHECK) == 0)    {      long min, max;      offsetT test;      if ((operand->flags & MN10200_OPERAND_SIGNED) != 0)	{	  max = (1 << (operand->bits - 1)) - 1;	  min = - (1 << (operand->bits - 1));	}      else	{	  max = (1 << operand->bits) - 1;	  min = 0;	}      test = val;      if (test < (offsetT) min || test > (offsetT) max)	return 0;      else	return 1;    }  return 1;}

⌨️ 快捷键说明

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