tc-ns32k.c

来自「基于4个mips核的noc设计」· C语言 代码 · 共 2,407 行 · 第 1/4 页

C
2,407
字号
	  /* We can apply default, don't goof.  */	  if (parse (desc->default_args, 1) != 1)	    /* Check error in default.  */	    as_fatal (_("Wrong numbers of operands in default, check ns32k-opcodes.h"));	}      else	{	  as_fatal (_("Wrong number of operands"));	}    }  for (i = 0; i < IIF_ENTRIES; i++)    /* Mark all entries as void.  */    iif.iifP[i].type = 0;  /* Build opcode iif-entry.  */  iif.instr_size = desc->opcode_size / 8;  IIF (1, 1, iif.instr_size, desc->opcode_seed, 0, 0, 0, 0, 0, 0, -1, 0);  /* This call encodes operands to iif format.  */  if (argc)    {      encode_operand (argc,		      argv,		      &desc->operands[0],		      &suffix[0],		      desc->im_size,		      desc->opcode_size);    }  return recursive_level;}/* Convert iif to fragments.  From this point we start to dribble with   functions in other files than this one.(Except hash.c) So, if it's   possible to make an iif for an other CPU, you don't need to know   what frags, relax, obstacks, etc is in order to port this   assembler. You only need to know if it's possible to reduce your   cpu-instruction to iif-format (takes some work) and adopt the other   md_? parts according to given instructions Note that iif was   invented for the clean ns32k`s architecure.  *//* GAS for the ns32k has a problem. PC relative displacements are   relative to the address of the opcode, not the address of the   operand. We used to keep track of the offset between the operand   and the opcode in pcrel_adjust for each frag and each fix. However,   we get into trouble where there are two or more pc-relative   operands and the size of the first one can't be determined. Then in   the relax phase, the size of the first operand will change and   pcrel_adjust will no longer be correct.  The current solution is   keep a pointer to the frag with the opcode in it and the offset in   that frag for each frag and each fix. Then, when needed, we can   always figure out how far it is between the opcode and the pcrel   object.  See also md_pcrel_adjust and md_fix_pcrel_adjust.  For   objects not part of an instruction, the pointer to the opcode frag   is always zero.  */voidconvert_iif (){  int i;  bit_fixS *j;  fragS *inst_frag;  unsigned int inst_offset;  char *inst_opcode;  char *memP;  int l;  int k;  char type;  char size = 0;  int size_so_far;  memP = frag_more (0);  inst_opcode = memP;  inst_offset = (memP - frag_now->fr_literal);  inst_frag = frag_now;  for (i = 0; i < IIF_ENTRIES; i++)    {      if (type = iif.iifP[i].type)	{	  /* The object exist, so handle it.  */	  switch (size = iif.iifP[i].size)	    {	    case 42:	      size = 0;	      /* It's a bitfix that operates on an existing object.  */	      if (iif.iifP[i].bit_fixP->fx_bit_base)		/* Expand fx_bit_base to point at opcode.  */		iif.iifP[i].bit_fixP->fx_bit_base = (long) inst_opcode;	      /* Fall through.  */	    case 8:		/* bignum or doublefloat */	    case 1:	    case 2:	    case 3:	    case 4:	      /* The final size in objectmemory is known.  */	      memP = frag_more(size);	      j = iif.iifP[i].bit_fixP;	      switch (type)		{		case 1:	/* The object is pure binary.  */		  if (j || iif.iifP[i].pcrel)		    {		      fix_new_ns32k (frag_now,				     (long) (memP - frag_now->fr_literal),				     size,				     0,				     iif.iifP[i].object,				     iif.iifP[i].pcrel,				     iif.iifP[i].im_disp,				     j,				     iif.iifP[i].bsr,	/* sequent hack */				     inst_frag, inst_offset);		    }		  else		    {		      /* Good, just put them bytes out.  */		      switch (iif.iifP[i].im_disp)			{			case 0:			  md_number_to_chars (memP, iif.iifP[i].object, size);			  break;			case 1:			  md_number_to_disp (memP, iif.iifP[i].object, size);			  break;			default:			  as_fatal (_("iif convert internal pcrel/binary"));			}		    }		  break;		case 2:		  /* The object is a pointer at an expression, so                     unpack it, note that bignums may result from the                     expression.  */		  evaluate_expr (&exprP, (char *) iif.iifP[i].object);		  if (exprP.X_op == O_big || size == 8)		    {		      if ((k = exprP.X_add_number) > 0)			{			  /* We have a bignum ie a quad. This can only                             happens in a long suffixed instruction.  */			  if (k * 2 > size)			    as_warn (_("Bignum too big for long"));			  if (k == 3)			    memP += 2;			  for (l = 0; k > 0; k--, l += 2)			    {			      md_number_to_chars (memP + l,						  generic_bignum[l >> 1],						  sizeof (LITTLENUM_TYPE));			    }			}		      else			{			  /* flonum.  */			  LITTLENUM_TYPE words[4];			  switch (size)			    {			    case 4:			      gen_to_words (words, 2, 8);			      md_number_to_imm (memP, (long) words[0],						sizeof (LITTLENUM_TYPE));			      md_number_to_imm (memP + sizeof (LITTLENUM_TYPE),						(long) words[1],						sizeof (LITTLENUM_TYPE));			      break;			    case 8:			      gen_to_words (words, 4, 11);			      md_number_to_imm (memP, (long) words[0],						sizeof (LITTLENUM_TYPE));			      md_number_to_imm (memP + sizeof (LITTLENUM_TYPE),						(long) words[1],						sizeof (LITTLENUM_TYPE));			      md_number_to_imm ((memP + 2						 * sizeof (LITTLENUM_TYPE)),						(long) words[2],						sizeof (LITTLENUM_TYPE));			      md_number_to_imm ((memP + 3						 * sizeof (LITTLENUM_TYPE)),						(long) words[3],						sizeof (LITTLENUM_TYPE));			      break;			    }			}		      break;		    }		  if (j ||		      exprP.X_add_symbol ||		      exprP.X_op_symbol ||		      iif.iifP[i].pcrel)		    {		      /* The expression was undefined due to an                         undefined label. Create a fix so we can fix                         the object later.  */		      exprP.X_add_number += iif.iifP[i].object_adjust;		      fix_new_ns32k_exp (frag_now,					 (long) (memP - frag_now->fr_literal),					 size,					 &exprP,					 iif.iifP[i].pcrel,					 iif.iifP[i].im_disp,					 j,					 iif.iifP[i].bsr,					 inst_frag, inst_offset);		    }		  else		    {		      /* Good, just put them bytes out.  */		      switch (iif.iifP[i].im_disp)			{			case 0:			  md_number_to_imm (memP, exprP.X_add_number, size);			  break;			case 1:			  md_number_to_disp (memP, exprP.X_add_number, size);			  break;			default:			  as_fatal (_("iif convert internal pcrel/pointer"));			}		    }		  break;		default:		  as_fatal (_("Internal logic error in iif.iifP[n].type"));		}	      break;	    case 0:	      /* Too bad, the object may be undefined as far as its		 final nsize in object memory is concerned.  The size		 of the object in objectmemory is not explicitly		 given.  If the object is defined its length can be		 determined and a fix can replace the frag.  */	      {		evaluate_expr (&exprP, (char *) iif.iifP[i].object);		if ((exprP.X_add_symbol || exprP.X_op_symbol) &&		    !iif.iifP[i].pcrel)		  {		    /* Size is unknown until link time so have to                       allow 4 bytes.  */		    size = 4;		    memP = frag_more(size);		    fix_new_ns32k_exp (frag_now,				       (long) (memP - frag_now->fr_literal),				       size,				       &exprP,				       0, /* never iif.iifP[i].pcrel, */				       1, /* always iif.iifP[i].im_disp */				       (bit_fixS *) 0, 0,				       inst_frag,				       inst_offset);		    break;		/* exit this absolute hack */		  }		if (exprP.X_add_symbol || exprP.X_op_symbol)		  {		    /* Frag it.  */		    if (exprP.X_op_symbol)		      {			/* We cant relax this case.  */			as_fatal (_("Can't relax difference"));		      }		    else		      {			/* Size is not important.  This gets fixed by			   relax, but we assume 0 in what follows.  */			memP = frag_more(4); /* Max size.  */			size = 0;			{			  fragS *old_frag = frag_now;			  frag_variant (rs_machine_dependent,					4, /* Max size.  */					0, /* Size.  */					IND (BRANCH, UNDEF), /* Expecting                                                                the worst.  */					exprP.X_add_symbol,					exprP.X_add_number,					inst_opcode);			  frag_opcode_frag (old_frag) = inst_frag;			  frag_opcode_offset (old_frag) = inst_offset;			  frag_bsr (old_frag) = iif.iifP[i].bsr;			}		      }		  }		else		  {		    /* This duplicates code in md_number_to_disp.  */		    if (-64 <= exprP.X_add_number && exprP.X_add_number <= 63)		      {			size = 1;		      }		    else		      {			if (-8192 <= exprP.X_add_number			    && exprP.X_add_number <= 8191)			  {			    size = 2;			  }			else			  {			    if (-0x20000000 <= exprP.X_add_number				&& exprP.X_add_number<=0x1fffffff)			      {				size = 4;			      }			    else			      {				as_warn (_("Displacement to large for :d"));				size = 4;			      }			  }		      }		    memP = frag_more (size);		    md_number_to_disp (memP, exprP.X_add_number, size);		  }	      }	      break;	    default:	      as_fatal (_("Internal logic error in iif.iifP[].type"));	    }	}    }}#ifdef BFD_ASSEMBLER/* This functionality should really be in the bfd library.  */static bfd_reloc_code_real_typereloc (int size, int pcrel, int type){  int length, index;  bfd_reloc_code_real_type relocs[] =  {    BFD_RELOC_NS32K_IMM_8,    BFD_RELOC_NS32K_IMM_16,    BFD_RELOC_NS32K_IMM_32,    BFD_RELOC_NS32K_IMM_8_PCREL,    BFD_RELOC_NS32K_IMM_16_PCREL,    BFD_RELOC_NS32K_IMM_32_PCREL,    /* ns32k displacements.  */    BFD_RELOC_NS32K_DISP_8,    BFD_RELOC_NS32K_DISP_16,    BFD_RELOC_NS32K_DISP_32,    BFD_RELOC_NS32K_DISP_8_PCREL,    BFD_RELOC_NS32K_DISP_16_PCREL,    BFD_RELOC_NS32K_DISP_32_PCREL,    /* Normal 2's complement.  */    BFD_RELOC_8,    BFD_RELOC_16,    BFD_RELOC_32,    BFD_RELOC_8_PCREL,    BFD_RELOC_16_PCREL,    BFD_RELOC_32_PCREL  };  switch (size)    {    case 1:      length = 0;      break;    case 2:      length = 1;      break;    case 4:      length = 2;      break;    default:      length = -1;      break;    }  index = length + 3 * pcrel + 6 * type;  if (index >= 0 && index < sizeof (relocs) / sizeof (relocs[0]))    return relocs[index];  if (pcrel)    as_bad (_("Can not do %d byte pc-relative relocation for storage type %d"),	    size, type);  else    as_bad (_("Can not do %d byte relocation for storage type %d"),	    size, type);  return BFD_RELOC_NONE;}#endifvoidmd_assemble (line)     char *line;{  freeptr = freeptr_static;  parse (line, 0);		/* Explode line to more fix form in iif.  */  convert_iif ();		/* Convert iif to frags, fix's etc.  */#ifdef SHOW_NUM  printf (" \t\t\t%s\n", line);#endif}voidmd_begin (){  /* Build a hashtable of the instructions.  */  const struct ns32k_opcode *ptr;  const char *stat;  inst_hash_handle = hash_new ();  for (ptr = ns32k_opcodes; ptr < endop; ptr++)    {      if ((stat = hash_insert (inst_hash_handle, ptr->name, (char *) ptr)))	/* Fatal.  */	as_fatal (_("Can't hash %s: %s"), ptr->name, stat);    }  /* Some private space please!  */  freeptr_static = (char *) malloc (PRIVATE_SIZE);}/* Must be equal to MAX_PRECISON in atof-ieee.c.  */#define MAX_LITTLENUMS 6/* Turn the string pointed to by litP into a floating point constant   of type TYPE, and emit the appropriate bytes.  The number of   LITTLENUMS emitted is stored in *SIZEP.  An error message is   returned, or NULL on OK.  */char *md_atof (type, litP, sizeP)     char type;     char *litP;     int *sizeP;{  int prec;  LITTLENUM_TYPE words[MAX_LITTLENUMS];  LITTLENUM_TYPE *wordP;  char *t;  switch (type)    {    case 'f':      prec = 2;      break;    case 'd':      prec = 4;      break;    default:      *sizeP = 0;      return _("Bad call to MD_ATOF()");    }  t = atof_ieee (input_line_pointer, type, words);  if (t)    input_line_pointer = t;  *sizeP = prec * sizeof (LITTLENUM_TYPE);  for (wordP = words + prec; prec--;)    {      md_number_to_chars (litP, (long) (*--wordP), sizeof (LITTLENUM_TYPE));      litP += sizeof (LITTLENUM_TYPE);    }  return 0;}/* Convert number to chars in correct order.  */voidmd_number_to_chars (buf, value, nbytes)     char *buf;     valueT value;     int nbytes;{  number_to_chars_littleendian (buf, value, nbytes);}/* This is a variant of md_numbers_to_chars. The reason for its'   existence is the fact that ns32k uses Huffman coded   displacements. This implies that the bit order is reversed in   displacements and that they are prefixed with a size-tag.   binary: msb -> lsb   0xxxxxxx				byte   10xxxxxx xxxxxxxx			word   11xxxxxx xxxxxxxx xxxxxxxx xxxxxxxx	double word   This must be taken care of and we do it here!  */static voidmd_number_to_disp (buf, val, n)     char *buf;     long val;     char n;{  switch (n)    {    case 1:      if (val < -64 || val > 63)	as_warn (_("Byte displacement out of range.  line number not valid"));      val &= 0x7f;#ifdef SHOW_NUM      printf ("%x ", val & 0xff);#endif      *buf++ = val;      break;    case 2:      if (val < -8192 || val > 8191)	as_warn (_("Word displacement out of range.  line number not valid"));      val &= 0x3fff;      val |= 0x8000;#ifdef SHOW_NUM      printf ("%x ", val >> 8 & 0xff);#endif      *buf++ = (val >> 8);#ifdef SHOW_NUM      printf ("%x ", val & 0xff);#endif      *buf++ = val;      break;    case 4:      if (val < -0x20000000 || val >= 0x20000000)	as_warn (_("Double word displacement out of range"));      val |= 0xc0000000;#ifdef SHOW_NUM      printf ("%x ", val >> 24 & 0xff);#endif      *buf++ = (val >> 24);#ifdef SHOW_NUM      printf ("%x ", val >> 16 & 0xff);#endif      *buf++ = (val >> 16);#ifdef SHOW_NUM      printf ("%x ", val >> 8 & 0xff);#endif      *buf++ = (val >> 8);#ifdef SHOW_NUM      printf ("%x ", val & 0xff);#endif      *buf++ = val;      break;    default:      as_fatal (_("Internal logic error.  line %s, file \"%s\""),		__LINE__, __FILE__);    }}static voidmd_number_to_imm (buf, val, n)     char *buf;     long val;     char n;{  switch (n)    {    case 1:#ifdef SHOW_NUM      printf ("%x ", val & 0xff);#endif      *buf++ = val;      break;    case 2:#ifdef SHOW_NUM      printf ("%x ", val >> 8 & 0xff);#endif      *buf++ = (val >> 8);#ifdef SHOW_NUM      printf ("%x ", val & 0xff);#endif      *buf++ = val;      break;    case 4:#ifdef SHOW_NUM      printf ("%x ", val >> 24 & 0xff);#endif      *buf++ = (val >> 24);#ifdef SHOW_NUM      printf ("%x ", val >> 16 & 0xff);#endif      *buf++ = (val >> 16);#ifdef SHOW_NUM      printf ("%x ", val >> 8 & 0xff);#endif      *buf++ = (val >> 8);#ifdef SHOW_NUM      printf ("%x ", val & 0xff);#endif      *buf++ = val;      break;    default:      as_fatal (_("Internal logic error. line %s, file \"%s\""),

⌨️ 快捷键说明

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