tc-ns32k.c

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

C
2,407
字号
		__LINE__, __FILE__);    }}/* Fast bitfiddling support.  *//* Mask used to zero bitfield before oring in the true field.  */static unsigned long l_mask[] ={  0xffffffff, 0xfffffffe, 0xfffffffc, 0xfffffff8,  0xfffffff0, 0xffffffe0, 0xffffffc0, 0xffffff80,  0xffffff00, 0xfffffe00, 0xfffffc00, 0xfffff800,  0xfffff000, 0xffffe000, 0xffffc000, 0xffff8000,  0xffff0000, 0xfffe0000, 0xfffc0000, 0xfff80000,  0xfff00000, 0xffe00000, 0xffc00000, 0xff800000,  0xff000000, 0xfe000000, 0xfc000000, 0xf8000000,  0xf0000000, 0xe0000000, 0xc0000000, 0x80000000,};static unsigned long r_mask[] ={  0x00000000, 0x00000001, 0x00000003, 0x00000007,  0x0000000f, 0x0000001f, 0x0000003f, 0x0000007f,  0x000000ff, 0x000001ff, 0x000003ff, 0x000007ff,  0x00000fff, 0x00001fff, 0x00003fff, 0x00007fff,  0x0000ffff, 0x0001ffff, 0x0003ffff, 0x0007ffff,  0x000fffff, 0x001fffff, 0x003fffff, 0x007fffff,  0x00ffffff, 0x01ffffff, 0x03ffffff, 0x07ffffff,  0x0fffffff, 0x1fffffff, 0x3fffffff, 0x7fffffff,};#define MASK_BITS 31/* Insert bitfield described by field_ptr and val at buf   This routine is written for modification of the first 4 bytes pointed   to by buf, to yield speed.   The ifdef stuff is for selection between a ns32k-dependent routine   and a general version. (My advice: use the general version!).  */static voidmd_number_to_field (buf, val, field_ptr)     register char *buf;     register long val;     register bit_fixS *field_ptr;{  register unsigned long object;  register unsigned long mask;  /* define ENDIAN on a ns32k machine */#ifdef ENDIAN  register unsigned long *mem_ptr;#else  register char *mem_ptr;#endif  if (field_ptr->fx_bit_min <= val && val <= field_ptr->fx_bit_max)    {#ifdef ENDIAN      if (field_ptr->fx_bit_base)	/* Override buf.  */	mem_ptr = (unsigned long *) field_ptr->fx_bit_base;      else	mem_ptr = (unsigned long *) buf;      mem_ptr = ((unsigned long *)		 ((char *) mem_ptr + field_ptr->fx_bit_base_adj));#else      if (field_ptr->fx_bit_base)	mem_ptr = (char *) field_ptr->fx_bit_base;      else	mem_ptr = buf;      mem_ptr += field_ptr->fx_bit_base_adj;#endif#ifdef ENDIAN      /* We have a nice ns32k machine with lowbyte at low-physical mem.  */      object = *mem_ptr;	/* get some bytes */#else /* OVE Goof! the machine is a m68k or dito */      /* That takes more byte fiddling.  */      object = 0;      object |= mem_ptr[3] & 0xff;      object <<= 8;      object |= mem_ptr[2] & 0xff;      object <<= 8;      object |= mem_ptr[1] & 0xff;      object <<= 8;      object |= mem_ptr[0] & 0xff;#endif      mask = 0;      mask |= (r_mask[field_ptr->fx_bit_offset]);      mask |= (l_mask[field_ptr->fx_bit_offset + field_ptr->fx_bit_size]);      object &= mask;      val += field_ptr->fx_bit_add;      object |= ((val << field_ptr->fx_bit_offset) & (mask ^ 0xffffffff));#ifdef ENDIAN      *mem_ptr = object;#else      mem_ptr[0] = (char) object;      object >>= 8;      mem_ptr[1] = (char) object;      object >>= 8;      mem_ptr[2] = (char) object;      object >>= 8;      mem_ptr[3] = (char) object;#endif    }  else    {      as_warn (_("Bit field out of range"));    }}intmd_pcrel_adjust (fragP)     fragS *fragP;{  fragS *opcode_frag;  addressT opcode_address;  unsigned int offset;  opcode_frag = frag_opcode_frag (fragP);  if (opcode_frag == 0)    return 0;  offset = frag_opcode_offset (fragP);  opcode_address = offset + opcode_frag->fr_address;  return fragP->fr_address + fragP->fr_fix - opcode_address;}intmd_fix_pcrel_adjust (fixP)     fixS *fixP;{  fragS *fragP = fixP->fx_frag;  fragS *opcode_frag;  addressT opcode_address;  unsigned int offset;  opcode_frag = fix_opcode_frag (fixP);  if (opcode_frag == 0)    return 0;  offset = fix_opcode_offset (fixP);  opcode_address = offset + opcode_frag->fr_address;  return fixP->fx_where + fixP->fx_frag->fr_address - opcode_address;}/* Apply a fixS (fixup of an instruction or data that we didn't have   enough info to complete immediately) to the data in a frag.   On the ns32k, everything is in a different format, so we have broken   out separate functions for each kind of thing we could be fixing.   They all get called from here.  */#ifdef BFD_ASSEMBLERintmd_apply_fix (fixP, valp)     fixS *fixP;     valueT *valp;#elsevoidmd_apply_fix (fixP, val)     fixS *fixP;     long val;#endif{#ifdef BFD_ASSEMBLER  long val = *valp;#endif  fragS *fragP = fixP->fx_frag;  char *buf = fixP->fx_where + fixP->fx_frag->fr_literal;  if (fix_bit_fixP (fixP))    {				/* Bitfields to fix, sigh.  */      md_number_to_field (buf, val, fix_bit_fixP (fixP));    }  else    switch (fix_im_disp (fixP))      {      case 0:			/* Immediate field.  */	md_number_to_imm (buf, val, fixP->fx_size);	break;      case 1:			/* Displacement field.  */	/* Calculate offset */	{	  md_number_to_disp (buf,			     (fixP->fx_pcrel ? val + md_fix_pcrel_adjust (fixP)			      : val), fixP->fx_size);	}	break;      case 2:			/* Pointer in a data object.  */	md_number_to_chars (buf, val, fixP->fx_size);	break;      }#ifdef BSD_ASSEMBLER  return 1;#endif}/* Convert a relaxed displacement to ditto in final output */#ifndef BFD_ASSEMBLERvoidmd_convert_frag (headers, sec, fragP)     object_headers *headers;     segT sec;     register fragS *fragP;#elsevoidmd_convert_frag (abfd, sec, fragP)     bfd *abfd;     segT sec;     register fragS *fragP;#endif{  long disp;  long ext = 0;  /* Address in gas core of the place to store the displacement.  */  register char *buffer_address = fragP->fr_fix + fragP->fr_literal;  /* Address in object code of the displacement.  */  int object_address;  fragS *opcode_frag;  switch (fragP->fr_subtype)    {    case IND (BRANCH, BYTE):      ext = 1;      break;    case IND (BRANCH, WORD):      ext = 2;      break;    case IND (BRANCH, DOUBLE):      ext = 4;      break;    }  if (ext == 0)    return;  know (fragP->fr_symbol);  object_address = fragP->fr_fix + fragP->fr_address;  /* The displacement of the address, from current location.  */  disp = (S_GET_VALUE (fragP->fr_symbol) + fragP->fr_offset) - object_address;#ifdef BFD_ASSEMBLER  disp += symbol_get_frag (fragP->fr_symbol)->fr_address;#endif  disp += md_pcrel_adjust (fragP);  md_number_to_disp (buffer_address, (long) disp, (int) ext);  fragP->fr_fix += ext;}/* This function returns the estimated size a variable object will occupy,   one can say that we tries to guess the size of the objects before we   actually know it.  */intmd_estimate_size_before_relax (fragP, segment)     register fragS *fragP;     segT segment;{  if (fragP->fr_subtype == IND (BRANCH, UNDEF))    {      if (S_GET_SEGMENT (fragP->fr_symbol) != segment)	{	  /* We don't relax symbols defined in another segment.  The	     thing to do is to assume the object will occupy 4 bytes.  */	  fix_new_ns32k (fragP,			 (int) (fragP->fr_fix),			 4,			 fragP->fr_symbol,			 fragP->fr_offset,			 1,			 1,			 0,			 frag_bsr(fragP), /*sequent hack */			 frag_opcode_frag (fragP),			 frag_opcode_offset (fragP));	  fragP->fr_fix += 4;#if 0	  fragP->fr_opcode[1] = 0xff;#endif	  frag_wane (fragP);	  return 4;	}      /* Relaxable case.  Set up the initial guess for the variable	 part of the frag.  */      fragP->fr_subtype = IND (BRANCH, BYTE);    }  if (fragP->fr_subtype >= sizeof (md_relax_table) / sizeof (md_relax_table[0]))    abort ();  /* Return the size of the variable part of the frag.  */  return md_relax_table[fragP->fr_subtype].rlx_length;}int md_short_jump_size = 3;int md_long_jump_size = 5;const int md_reloc_size = 8;	/* Size of relocation record.  */voidmd_create_short_jump (ptr, from_addr, to_addr, frag, to_symbol)     char *ptr;     addressT from_addr, to_addr;     fragS *frag;     symbolS *to_symbol;{  valueT offset;  offset = to_addr - from_addr;  md_number_to_chars (ptr, (valueT) 0xEA, 1);  md_number_to_disp (ptr + 1, (valueT) offset, 2);}voidmd_create_long_jump (ptr, from_addr, to_addr, frag, to_symbol)     char *ptr;     addressT from_addr, to_addr;     fragS *frag;     symbolS *to_symbol;{  valueT offset;  offset = to_addr - from_addr;  md_number_to_chars (ptr, (valueT) 0xEA, 1);  md_number_to_disp (ptr + 1, (valueT) offset, 4);}CONST char *md_shortopts = "m:";struct option md_longopts[] ={  {NULL, no_argument, NULL, 0}};size_t md_longopts_size = sizeof (md_longopts);intmd_parse_option (c, arg)     int c;     char *arg;{  switch (c)    {    case 'm':      if (!strcmp (arg, "32032"))	{	  cpureg = cpureg_032;	  mmureg = mmureg_032;	}      else if (!strcmp (arg, "32532"))	{	  cpureg = cpureg_532;	  mmureg = mmureg_532;	}      else	{	  as_bad (_("invalid architecture option -m%s"), arg);	  return 0;	}      break;    default:      return 0;    }  return 1;}voidmd_show_usage (stream)     FILE *stream;{  fprintf (stream, _("\NS32K options:\n\-m32032 | -m32532	select variant of NS32K architecture\n"));}/* Create a bit_fixS in obstack 'notes'.   This struct is used to profile the normal fix. If the bit_fixP is a   valid pointer (not NULL) the bit_fix data will be used to format   the fix.  */bit_fixS *bit_fix_new (size, offset, min, max, add, base_type, base_adj)     char size;			/* Length of bitfield		*/     char offset;		/* Bit offset to bitfield	*/     long min;			/* Signextended min for bitfield */     long max;			/* Signextended max for bitfield */     long add;			/* Add mask, used for huffman prefix */     long base_type;		/* 0 or 1, if 1 it's exploded to opcode ptr */     long base_adj;{  register bit_fixS *bit_fixP;  bit_fixP = (bit_fixS *) obstack_alloc (&notes, sizeof (bit_fixS));  bit_fixP->fx_bit_size = size;  bit_fixP->fx_bit_offset = offset;  bit_fixP->fx_bit_base = base_type;  bit_fixP->fx_bit_base_adj = base_adj;  bit_fixP->fx_bit_max = max;  bit_fixP->fx_bit_min = min;  bit_fixP->fx_bit_add = add;  return (bit_fixP);}voidfix_new_ns32k (frag, where, size, add_symbol, offset, pcrel,	       im_disp, bit_fixP, bsr, opcode_frag, opcode_offset)     fragS *frag;		/* Which frag? */     int where;			/* Where in that frag? */     int size;			/* 1, 2  or 4 usually.  */     symbolS *add_symbol;	/* X_add_symbol.  */     long offset;		/* X_add_number.  */     int pcrel;			/* TRUE if PC-relative relocation.  */     char im_disp;		/* true if the value to write is a				   displacement */     bit_fixS *bit_fixP;	/* pointer at struct of bit_fix's, ignored if				   NULL */     char bsr;			/* sequent-linker-hack: 1 when relocobject is				   a bsr */     fragS *opcode_frag;     unsigned int opcode_offset;{  fixS *fixP = fix_new (frag, where, size, add_symbol,			offset, pcrel,#ifdef BFD_ASSEMBLER			bit_fixP ? NO_RELOC : reloc (size, pcrel, im_disp)#else			NO_RELOC#endif			);  fix_opcode_frag (fixP) = opcode_frag;  fix_opcode_offset (fixP) = opcode_offset;  fix_im_disp (fixP) = im_disp;  fix_bsr (fixP) = bsr;  fix_bit_fixP (fixP) = bit_fixP;}voidfix_new_ns32k_exp (frag, where, size, exp, pcrel,		   im_disp, bit_fixP, bsr, opcode_frag, opcode_offset)     fragS *frag;		/* Which frag? */     int where;			/* Where in that frag? */     int size;			/* 1, 2  or 4 usually.  */     expressionS *exp;		/* Expression.  */     int pcrel;			/* TRUE if PC-relative relocation.  */     char im_disp;		/* true if the value to write is a				   displacement */     bit_fixS *bit_fixP;	/* pointer at struct of bit_fix's, ignored if				   NULL */     char bsr;			/* sequent-linker-hack: 1 when relocobject is				   a bsr */     fragS *opcode_frag;     unsigned int opcode_offset;{  fixS *fixP = fix_new_exp (frag, where, size, exp, pcrel,#ifdef BFD_ASSEMBLER			    bit_fixP ? NO_RELOC : reloc (size, pcrel, im_disp)#else			    NO_RELOC#endif			    );  fix_opcode_frag (fixP) = opcode_frag;  fix_opcode_offset (fixP) = opcode_offset;  fix_im_disp (fixP) = im_disp;  fix_bsr (fixP) = bsr;  fix_bit_fixP (fixP) = bit_fixP;}/* This is TC_CONS_FIX_NEW, called by emit_expr in read.c.  */voidcons_fix_new_ns32k (frag, where, size, exp)     fragS *frag;		/* Which frag? */     int where;			/* Where in that frag? */     int size;			/* 1, 2  or 4 usually.  */     expressionS *exp;		/* Expression.  */{  fix_new_ns32k_exp (frag, where, size, exp,		     0, 2, 0, 0, 0, 0);}/* We have no need to default values of symbols.  */symbolS *md_undefined_symbol (name)     char *name;{  return 0;}/* Round up a section size to the appropriate boundary.  */valueTmd_section_align (segment, size)     segT segment;     valueT size;{  return size;			/* Byte alignment is fine.  */}/* Exactly what point is a PC-relative offset relative TO?  On the   ns32k, they're relative to the start of the instruction.  */longmd_pcrel_from (fixP)     fixS *fixP;{  long res;  res = fixP->fx_where + fixP->fx_frag->fr_address;#ifdef SEQUENT_COMPATABILITY  if (frag_bsr (fixP->fx_frag))    res += 0x12			/* FOO Kludge alert!  */#endif      return res;}#ifdef BFD_ASSEMBLERarelent *tc_gen_reloc (section, fixp)     asection *section;     fixS *fixp;{  arelent *rel;  bfd_reloc_code_real_type code;  code = reloc (fixp->fx_size, fixp->fx_pcrel, fix_im_disp (fixp));  rel = (arelent *) xmalloc (sizeof (arelent));  rel->sym_ptr_ptr = (asymbol **) xmalloc (sizeof (asymbol *));  *rel->sym_ptr_ptr = symbol_get_bfdsym (fixp->fx_addsy);  rel->address = fixp->fx_frag->fr_address + fixp->fx_where;  if (fixp->fx_pcrel)    rel->addend = fixp->fx_addnumber;  else    rel->addend = 0;  rel->howto = bfd_reloc_type_lookup (stdoutput, code);  if (!rel->howto)    {      const char *name;      name = S_GET_NAME (fixp->fx_addsy);      if (name == NULL)	name = _("<unknown>");      as_fatal (_("Cannot find relocation type for symbol %s, code %d"),		name, (int) code);    }  return rel;}#else /* BFD_ASSEMBLER */#ifdef OBJ_AOUTvoidcons_fix_new_ns32k (where, fixP, segment_address_in_file)     char *where;     struct fix *fixP;     relax_addressT segment_address_in_file;{  /* In:  Length of relocation (or of address) in chars: 1, 2 or 4.     Out: GNU LD relocation length code: 0, 1, or 2.  */  static unsigned char nbytes_r_length[] = { 42, 0, 1, 42, 2 };  long r_symbolnum;  know (fixP->fx_addsy != NULL);  md_number_to_chars (where,       fixP->fx_frag->fr_address + fixP->fx_where - segment_address_in_file,		      4);  r_symbolnum = (S_IS_DEFINED (fixP->fx_addsy)		 ? S_GET_TYPE (fixP->fx_addsy)		 : fixP->fx_addsy->sy_number);  md_number_to_chars (where + 4,		      ((long) (r_symbolnum)		       | (long) (fixP->fx_pcrel << 24)		       | (long) (nbytes_r_length[fixP->fx_size] << 25)		       | (long) ((!S_IS_DEFINED (fixP->fx_addsy)) << 27)		       | (long) (fix_bsr (fixP) << 28)		       | (long) (fix_im_disp (fixP) << 29)),		      4);}#endif /* OBJ_AOUT */#endif /* BFD_ASSMEBLER */

⌨️ 快捷键说明

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