tc-m88k.c

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

C
1,462
字号
  unsigned offset = 0;  unsigned width = 0;  char *xp;  char *save_ptr;  xp = get_bf2 (param, '<');  save_ptr = input_line_pointer;  input_line_pointer = param;  if (*xp == 0)    {      /* We did not find '<'.  We have an offset (width implicitly 32).  */      param = get_bf_offset_expression (param, &offset);      input_line_pointer = save_ptr;      if (param == NULL)	return NULL;    }  else    {      *xp++ = 0;		/* Overwrite the '<' */      param = get_bf2 (xp, '>');      if (*param == 0)	return NULL;      *param++ = 0;		/* Overwrite the '>' */      width = get_absolute_expression ();      xp = get_bf_offset_expression (xp, &offset);      input_line_pointer = save_ptr;      if (xp + 1 != param)	return NULL;    }  *valp = ((width % 32) << 5) | (offset % 32);  return param;}static char *get_cr (param, regnop)     char *param;     unsigned *regnop;{  unsigned regno;  unsigned c;  if (!strncmp (param, "cr", 2))    {      param += 2;      regno = *param++ - '0';      if (regno < 10)	{	  if (regno == 0)	    {	      *regnop = 0;	      return param;	    }	  c = *param - '0';	  if (c < 10)	    {	      regno = regno * 10 + c;	      if (c < 64)		{		  *regnop = regno;		  return param + 1;		}	    }	  else	    {	      *regnop = regno;	      return param;	    }	}      return NULL;    }  param = match_name (param, cr_regs, regnop);  return param;}static char *get_fcr (param, regnop)     char *param;     unsigned *regnop;{  unsigned regno;  unsigned c;  if (!strncmp (param, "fcr", 3))    {      param += 3;      regno = *param++ - '0';      if (regno < 10)	{	  if (regno == 0)	    {	      *regnop = 0;	      return param;	    }	  c = *param - '0';	  if (c < 10)	    {	      regno = regno * 10 + c;	      if (c < 64)		{		  *regnop = regno;		  return param + 1;		}	    }	  else	    {	      *regnop = regno;	      return param;	    }	}      return NULL;    }  param = match_name (param, fcr_regs, regnop);  return param;}static char *get_vec9 (param, valp)     char *param;     unsigned *valp;{  unsigned val;  char *save_ptr;  save_ptr = input_line_pointer;  input_line_pointer = param;  val = get_absolute_expression ();  param = input_line_pointer;  input_line_pointer = save_ptr;  if (val >= 1 << 9)    as_warn (_("Expression truncated to 9 bits"));  *valp = val % (1 << 9);  return param;}static char *get_o6 (param, valp)     char *param;     unsigned *valp;{  unsigned val;  char *save_ptr;  save_ptr = input_line_pointer;  input_line_pointer = param;  val = get_absolute_expression ();  param = input_line_pointer;  input_line_pointer = save_ptr;  if (val & 0x3)    as_warn (_("Removed lower 2 bits of expression"));  *valp = val;  return(param);}#define hexval(z) \  (isdigit (z) ? (z) - '0' :						\   islower (z) ? (z) - 'a' + 10 : 					\   isupper (z) ? (z) - 'A' + 10 : -1)static char *getval (param, valp)     char *param;     unsigned int *valp;{  unsigned int val = 0;  unsigned int c;  c = *param++;  if (c == '0')    {      c = *param++;      if (c == 'x' || c == 'X')	{	  c = *param++;	  c = hexval (c);	  while (c < 16)	    {	      val = val * 16 + c;	      c = *param++;	      c = hexval (c);	    }	}      else	{	  c -= '0';	  while (c < 8)	    {	      val = val * 8 + c;	      c = *param++ - '0';	    }	}    }  else    {      c -= '0';      while (c < 10)	{	  val = val * 10 + c;	  c = *param++ - '0';	}    }  *valp = val;  return param - 1;}voidmd_number_to_chars (buf, val, nbytes)     char *buf;     valueT val;     int nbytes;{  number_to_chars_bigendian (buf, val, nbytes);}#if 0/* This routine is never called.  What is it for?   Ian Taylor, Cygnus Support 13 Jul 1993 */voidmd_number_to_imm (buf, val, nbytes, fixP, seg_type)     unsigned char *buf;     unsigned int val;     int nbytes;     fixS *fixP;     int seg_type;{  if (seg_type != N_TEXT || fixP->fx_r_type == NO_RELOC)    {      switch (nbytes)	{	case 4:	  *buf++ = val >> 24;	  *buf++ = val >> 16;	case 2:	  *buf++ = val >> 8;	case 1:	  *buf = val;	  break;	default:	  abort ();	}      return;    }  switch (fixP->fx_r_type)    {    case RELOC_IW16:      buf[2] = val >> 8;      buf[3] = val;      break;    case RELOC_LO16:      buf[0] = val >> 8;      buf[1] = val;      break;    case RELOC_HI16:      buf[0] = val >> 24;      buf[1] = val >> 16;      break;    case RELOC_PC16:      val += 4;      buf[0] = val >> 10;      buf[1] = val >> 2;      break;    case RELOC_PC26:      val += 4;      buf[0] |= (val >> 26) & 0x03;      buf[1] = val >> 18;      buf[2] = val >> 10;      buf[3] = val >> 2;      break;    case RELOC_32:      buf[0] = val >> 24;      buf[1] = val >> 16;      buf[2] = val >> 8;      buf[3] = val;      break;    default:      as_fatal (_("Bad relocation type"));      break;    }}#endif /* 0 */voidmd_number_to_disp (buf, val, nbytes)     char *buf;     int val;     int nbytes;{  as_fatal (_("md_number_to_disp not defined"));  md_number_to_chars (buf, val, nbytes);}voidmd_number_to_field (buf, val, nbytes)     char *buf;     int val;     int nbytes;{  as_fatal (_("md_number_to_field not defined"));  md_number_to_chars (buf, val, nbytes);}#define MAX_LITTLENUMS 6/* Turn a string in input_line_pointer into a floating point constant of type   type, and store the appropriate bytes in *litP.  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':    case 'F':    case 's':    case 'S':      prec = 2;      break;    case 'd':    case 'D':    case 'r':    case 'R':      prec = 4;      break;    case 'x':    case 'X':      prec = 6;      break;    case 'p':    case 'P':      prec = 6;      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--;)    {      md_number_to_chars (litP, (long) (*wordP++), sizeof (LITTLENUM_TYPE));      litP += sizeof (LITTLENUM_TYPE);    }  return 0;}int md_short_jump_size = 4;voidmd_create_short_jump (ptr, from_addr, to_addr, frag, to_symbol)     char *ptr;     addressT from_addr, to_addr;     fragS *frag;     symbolS *to_symbol;{  ptr[0] = (char) 0xc0;  ptr[1] = 0x00;  ptr[2] = 0x00;  ptr[3] = 0x00;  fix_new (frag,	   ptr - frag->fr_literal,	   4,	   to_symbol,	   (offsetT) 0,	   0,	   RELOC_PC26);		/* Botch: Shouldn't this be RELOC_PC16? */}int md_long_jump_size = 4;voidmd_create_long_jump (ptr, from_addr, to_addr, frag, to_symbol)     char *ptr;     addressT from_addr, to_addr;     fragS *frag;     symbolS *to_symbol;{  ptr[0] = (char) 0xc0;  ptr[1] = 0x00;  ptr[2] = 0x00;  ptr[3] = 0x00;  fix_new (frag,	   ptr - frag->fr_literal,	   4,	   to_symbol,	   (offsetT) 0,	   0,	   RELOC_PC26);}intmd_estimate_size_before_relax (fragP, segment_type)     fragS *fragP;     segT segment_type;{  as_fatal (_("Relaxation should never occur"));  return (-1);}#if 0/* As far as I can tell, this routine is never called.  What is it   doing here?   Ian Taylor, Cygnus Support 13 Jul 1993 *//* * Risc relocations are completely different, so it needs * this machine dependent routine to emit them. */voidemit_relocations (fixP, segment_address_in_file)     fixS *fixP;     relax_addressT segment_address_in_file;{  struct reloc_info_m88k ri;  symbolS *symbolP;  extern char *next_object_file_charP;  bzero ((char *) &ri, sizeof (ri));  for (; fixP; fixP = fixP->fx_next)    {      if (fixP->fx_r_type >= NO_RELOC)	{	  fprintf (stderr, "fixP->fx_r_type = %d\n", fixP->fx_r_type);	  abort ();	}      if ((symbolP = fixP->fx_addsy) != NULL)	{	  ri.r_address = fixP->fx_frag->fr_address +	    fixP->fx_where - segment_address_in_file;	  if ((symbolP->sy_type & N_TYPE) == N_UNDF)	    {	      ri.r_extern = 1;	      ri.r_symbolnum = symbolP->sy_number;	    }	  else	    {	      ri.r_extern = 0;	      ri.r_symbolnum = symbolP->sy_type & N_TYPE;	    }	  if (symbolP && symbol_get_frag (symbolP))	    {	      ri.r_addend = symbol_get_frag (symbolP)->fr_address;	    }	  ri.r_type = fixP->fx_r_type;	  if (fixP->fx_pcrel)	    {	      ri.r_addend -= ri.r_address;	    }	  else	    {	      ri.r_addend = fixP->fx_addnumber;	    }	  append (&next_object_file_charP, (char *) &ri, sizeof (ri));	}    }}#endif /* 0 */#if 0/* This routine can be subsumed by s_lcomm in read.c.   Ian Taylor, Cygnus Support 13 Jul 1993 */static voids_bss (){  char *name;  char c;  char *p;  int temp, bss_align;  symbolS *symbolP;  name = input_line_pointer;  c = get_symbol_end ();  p = input_line_pointer;  *p = c;  SKIP_WHITESPACE ();  if (*input_line_pointer != ',')    {      as_warn (_("Expected comma after name"));      ignore_rest_of_line ();      return;    }  input_line_pointer++;  if ((temp = get_absolute_expression ()) < 0)    {      as_warn (_("BSS length (%d.) <0! Ignored."), temp);      ignore_rest_of_line ();      return;    }  *p = 0;  symbolP = symbol_find_or_make (name);  *p = c;  if (*input_line_pointer == ',')    {      input_line_pointer++;      bss_align = get_absolute_expression ();    }  else    bss_align = 0;  if (!S_IS_DEFINED(symbolP)      || S_GET_SEGMENT(symbolP) == SEG_BSS)    {      if (! need_pass_2)	{	  char *p;	  segT current_seg = now_seg;	  subsegT current_subseg = now_subseg;	  subseg_set (SEG_BSS, 1); /* switch to bss	*/	  if (bss_align)	    frag_align (bss_align, 0, 0);	  /* detach from old frag */	  if (symbolP->sy_type == N_BSS && symbol_get_frag (symbolP) != NULL)	    symbol_get_frag (symbolP)->fr_symbol = NULL;	  symbol_set_frag (symbolP, frag_now);	  p = frag_var (rs_org, 1, 1, (relax_substateT)0, symbolP,			(offsetT) temp, (char *)0);	  *p = 0;	  S_SET_SEGMENT (symbolP, SEG_BSS);	  subseg_set (current_seg, current_subseg);	}    }  else    {      as_warn (_("Ignoring attempt to re-define symbol %s."), name);    }  while (!is_end_of_line[(unsigned char) *input_line_pointer])    {      input_line_pointer++;    }}#endif /* 0 */#ifdef M88KCOFF/* These functions are needed if we are linking with obj-coffbfd.c.   That file may be replaced by a more BFD oriented version at some   point.  If that happens, these functions should be rexamined.   Ian Lance Taylor, Cygnus Support, 13 July 1993.  *//* Given a fixS structure (created by a call to fix_new, above),   return the BFD relocation type to use for it.  */shorttc_coff_fix2rtype (fixp)     fixS *fixp;{  switch (fixp->fx_r_type)    {    case RELOC_LO16:      return R_LVRT16;    case RELOC_HI16:      return R_HVRT16;    case RELOC_PC16:      return R_PCR16L;    case RELOC_PC26:      return R_PCR26L;    case RELOC_32:      return R_VRT32;    case RELOC_IW16:      return R_VRT16;    default:      abort ();    }}/* Apply a fixS to the object file.  Since COFF does not use addends   in relocs, the addend is actually stored directly in the object   file itself.  */voidmd_apply_fix (fixp, val)     fixS *fixp;     long val;{  char *buf;  buf = fixp->fx_frag->fr_literal + fixp->fx_where;  fixp->fx_offset = 0;  switch (fixp->fx_r_type)    {    case RELOC_IW16:      fixp->fx_offset = val >> 16;      buf[2] = val >> 8;      buf[3] = val;      break;    case RELOC_LO16:      fixp->fx_offset = val >> 16;      buf[0] = val >> 8;      buf[1] = val;      break;    case RELOC_HI16:      fixp->fx_offset = val >> 16;      buf[0] = val >> 8;      buf[1] = val;      break;    case RELOC_PC16:      buf[0] = val >> 10;      buf[1] = val >> 2;      break;    case RELOC_PC26:      buf[0] |= (val >> 26) & 0x03;      buf[1] = val >> 18;      buf[2] = val >> 10;      buf[3] = val >> 2;      break;    case RELOC_32:      buf[0] = val >> 24;      buf[1] = val >> 16;      buf[2] = val >> 8;      buf[3] = val;      break;    default:      abort ();    }}/* Where a PC relative offset is calculated from.  On the m88k they   are calculated from just after the instruction.  */longmd_pcrel_from (fixp)     fixS *fixp;{  switch (fixp->fx_r_type)    {    case RELOC_PC16:      return fixp->fx_frag->fr_address + fixp->fx_where - 2;    case RELOC_PC26:      return fixp->fx_frag->fr_address + fixp->fx_where;    default:      abort ();    }  /*NOTREACHED*/}/* Fill in rs_align_code fragments.  */voidm88k_handle_align (fragp)     fragS *fragp;{  static const unsigned char nop_pattern[] = { 0xf4, 0x00, 0x58, 0x00 };  int bytes;  char *p;  if (fragp->fr_type != rs_align_code)    return;  bytes = fragp->fr_next->fr_address - fragp->fr_address - fragp->fr_fix;  p = fragp->fr_literal + fragp->fr_fix;  if (bytes & 3)    {      int fix = bytes & 3;      memset (p, 0, fix);      p += fix;      bytes -= fix;      fragp->fr_fix += fix;    }  memcpy (p, nop_pattern, 4);  fragp->fr_var = 4;}#endif /* M88KCOFF */

⌨️ 快捷键说明

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