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

📄 tc-d30v.c

📁 基于4个mips核的noc设计
💻 C
📖 第 1 页 / 共 4 页
字号:
		  /* Turn an expression into a symbol for later resolution.  */		  if (X_op != O_absent && X_op != O_constant		      && X_op != O_symbol && X_op != O_register		      && X_op != O_big)		    {		      symbolS *sym = make_expr_symbol (&myops[j]);		      myops[j].X_op = X_op = O_symbol;		      myops[j].X_add_symbol = sym;		      myops[j].X_add_number = num = 0;		    }		  if (fm->form >= LONG)		    {		      /* If we're testing for a LONG format, either fits.  */		      if (X_op != O_constant && X_op != O_symbol)			match = 0;		    }		  else if (fm->form < LONG			   && ((fsize == FORCE_SHORT && X_op == O_symbol)			       || (fm->form == SHORT_D2 && j == 0)))		    match = 1;		  /* This is the tricky part.  Will the constant or symbol		     fit into the space in the current format?  */		  else if (X_op == O_constant)		    {		      if (check_range (num, bits, flags))			match = 0;		    }		  else if (X_op == O_symbol			   && S_IS_DEFINED (myops[j].X_add_symbol)			   && S_GET_SEGMENT (myops[j].X_add_symbol) == now_seg			   && opcode->reloc_flag == RELOC_PCREL)		    {		      /* If the symbol is defined, see if the value will fit			 into the form we're considering.  */		      fragS *f;		      long value;		      /* Calculate the current address by running through the			 previous frags and adding our current offset.  */		      value = 0;		      for (f = frchain_now->frch_root; f; f = f->fr_next)			value += f->fr_fix + f->fr_offset;		      value = (S_GET_VALUE (myops[j].X_add_symbol) - value			       - (obstack_next_free (&frchain_now->frch_obstack)				  - frag_now->fr_literal));		      if (check_range (value, bits, flags))			match = 0;		    }		  else		    match = 0;		}	    }#if 0	  printf ("through the loop: match=%d\n", match);#endif	  /* We're only done if the operands matched so far AND there	     are no more to check.  */	  if (match && myops[j].X_op == 0)	    {	      /* Final check - issue a warning if an odd numbered register		 is used as the first register in an instruction that reads		 or writes 2 registers.  */	      for (j = 0; fm->operands[j]; j++)		if (myops[j].X_op == O_register		    && (myops[j].X_add_number & 1)		    && (d30v_operand_table[fm->operands[j]].flags & OPERAND_2REG))		  as_warn (_("Odd numbered register used as target of multi-register instruction"));	      return fm;	    }	  fm = (struct d30v_format *) &d30v_format_table[++k];	}#if 0      printf ("trying another format: i=%d\n", i);#endif    }  return NULL;}/* 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->sym_ptr_ptr = (asymbol **) xmalloc (sizeof (asymbol *));  *reloc->sym_ptr_ptr = symbol_get_bfdsym (fixp->fx_addsy);  reloc->address = fixp->fx_frag->fr_address + fixp->fx_where;  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->addend = fixp->fx_addnumber;  return reloc;}intmd_estimate_size_before_relax (fragp, seg)     fragS *fragp;     asection *seg;{  abort ();  return 0;}longmd_pcrel_from_section (fixp, sec)     fixS *fixp;     segT sec;{  if (fixp->fx_addsy != (symbolS *) NULL      && (!S_IS_DEFINED (fixp->fx_addsy)	  || (S_GET_SEGMENT (fixp->fx_addsy) != sec)))    return 0;  return fixp->fx_frag->fr_address + fixp->fx_where;}intmd_apply_fix3 (fixp, valuep, seg)     fixS *fixp;     valueT *valuep;     segT seg;{  char *where;  unsigned long insn, insn2;  long value;  if (fixp->fx_addsy == (symbolS *) NULL)    {      value = *valuep;      fixp->fx_done = 1;    }  else if (fixp->fx_pcrel)    value = *valuep;  else    {      value = fixp->fx_offset;      if (fixp->fx_subsy != (symbolS *) NULL)	{	  if (S_GET_SEGMENT (fixp->fx_subsy) == absolute_section)	    value -= S_GET_VALUE (fixp->fx_subsy);	  else	    {	      /* We don't actually support subtracting a symbol.  */	      as_bad_where (fixp->fx_file, fixp->fx_line,			    _("expression too complex"));	    }	}    }  /* Fetch the instruction, insert the fully resolved operand     value, and stuff the instruction back again.  */  where = fixp->fx_frag->fr_literal + fixp->fx_where;  insn = bfd_getb32 ((unsigned char *) where);  switch (fixp->fx_r_type)    {    case BFD_RELOC_8:  /* Check for a bad .byte directive.  */      if (fixp->fx_addsy != NULL)	as_bad (_("line %d: unable to place address of symbol '%s' into a byte"),		fixp->fx_line, S_GET_NAME (fixp->fx_addsy));      else if (((unsigned)value) > 0xff)	as_bad (_("line %d: unable to place value %x into a byte"),		fixp->fx_line, value);      else	*(unsigned char *) where = value;      break;    case BFD_RELOC_16:  /* Check for a bad .short directive.  */      if (fixp->fx_addsy != NULL)	as_bad (_("line %d: unable to place address of symbol '%s' into a short"),		fixp->fx_line, S_GET_NAME (fixp->fx_addsy));      else if (((unsigned)value) > 0xffff)	as_bad (_("line %d: unable to place value %x into a short"),		fixp->fx_line, value);      else	bfd_putb16 ((bfd_vma) value, (unsigned char *) where);      break;    case BFD_RELOC_64:  /* Check for a bad .quad directive.  */      if (fixp->fx_addsy != NULL)	as_bad (_("line %d: unable to place address of symbol '%s' into a quad"),		fixp->fx_line, S_GET_NAME (fixp->fx_addsy));      else	{	  bfd_putb32 ((bfd_vma) value, (unsigned char *) where);	  bfd_putb32 (0, ((unsigned char *) where) + 4);	}      break;    case BFD_RELOC_D30V_6:      check_size (value, 6, fixp->fx_file, fixp->fx_line);      insn |= value & 0x3F;      bfd_putb32 ((bfd_vma) insn, (unsigned char *) where);      break;    case BFD_RELOC_D30V_9_PCREL:      if (fixp->fx_where & 0x7)	{	  if (fixp->fx_done)	    value += 4;	  else	    fixp->fx_r_type = BFD_RELOC_D30V_9_PCREL_R;	}      check_size (value, 9, fixp->fx_file, fixp->fx_line);      insn |= ((value >> 3) & 0x3F) << 12;      bfd_putb32 ((bfd_vma) insn, (unsigned char *) where);      break;    case BFD_RELOC_D30V_15:      check_size (value, 15, fixp->fx_file, fixp->fx_line);      insn |= (value >> 3) & 0xFFF;      bfd_putb32 ((bfd_vma) insn, (unsigned char *) where);      break;    case BFD_RELOC_D30V_15_PCREL:      if (fixp->fx_where & 0x7)	{	  if (fixp->fx_done)	    value += 4;	  else	    fixp->fx_r_type = BFD_RELOC_D30V_15_PCREL_R;	}      check_size (value, 15, fixp->fx_file, fixp->fx_line);      insn |= (value >> 3) & 0xFFF;      bfd_putb32 ((bfd_vma) insn, (unsigned char *) where);      break;    case BFD_RELOC_D30V_21:      check_size (value, 21, fixp->fx_file, fixp->fx_line);      insn |= (value >> 3) & 0x3FFFF;      bfd_putb32 ((bfd_vma) insn, (unsigned char *) where);      break;    case BFD_RELOC_D30V_21_PCREL:      if (fixp->fx_where & 0x7)	{	  if (fixp->fx_done)	    value += 4;	  else	    fixp->fx_r_type = BFD_RELOC_D30V_21_PCREL_R;	}      check_size (value, 21, fixp->fx_file, fixp->fx_line);      insn |= (value >> 3) & 0x3FFFF;      bfd_putb32 ((bfd_vma) insn, (unsigned char *) where);      break;    case BFD_RELOC_D30V_32:      insn2 = bfd_getb32 ((unsigned char *) where + 4);      insn |= (value >> 26) & 0x3F;		/* Top 6 bits.  */      insn2 |= ((value & 0x03FC0000) << 2);	/* Next 8 bits.  */      insn2 |= value & 0x0003FFFF;		/* Bottom 18 bits.  */      bfd_putb32 ((bfd_vma) insn, (unsigned char *) where);      bfd_putb32 ((bfd_vma) insn2, (unsigned char *) where + 4);      break;    case BFD_RELOC_D30V_32_PCREL:      insn2 = bfd_getb32 ((unsigned char *) where + 4);      insn |= (value >> 26) & 0x3F;		/* Top 6 bits.  */      insn2 |= ((value & 0x03FC0000) << 2);	/* Next 8 bits.  */      insn2 |= value & 0x0003FFFF;		/* Bottom 18 bits.  */      bfd_putb32 ((bfd_vma) insn, (unsigned char *) where);      bfd_putb32 ((bfd_vma) insn2, (unsigned char *) where + 4);      break;    case BFD_RELOC_32:      bfd_putb32 ((bfd_vma) value, (unsigned char *) where);      break;    default:      as_bad (_("line %d: unknown relocation type: 0x%x"),	      fixp->fx_line, fixp->fx_r_type);    }  return 0;}/* Called after the assembler has finished parsing the input file or   after a label is defined.  Because the D30V assembler sometimes   saves short instructions to see if it can package them with the   next instruction, there may be a short instruction that still needs   written.  */intd30v_cleanup (use_sequential)     int use_sequential;{  segT seg;  subsegT subseg;  if (prev_insn != -1)    {      seg = now_seg;      subseg = now_subseg;      subseg_set (prev_seg, prev_subseg);      write_1_short (&prev_opcode, (long) prev_insn, fixups->next,		     use_sequential);      subseg_set (seg, subseg);      prev_insn = -1;      if (use_sequential)	prev_mul32_p = false;    }  return 1;}static voidd30v_number_to_chars (buf, value, n)     char *buf;			/* Return 'nbytes' of chars here.  */     long long value;		/* The value of the bits.  */     int n;			/* Number of bytes in the output.  */{  while (n--)    {      buf[n] = value & 0xff;      value >>= 8;    }}/* This function is called at the start of every line.  It checks to   see if the first character is a '.', which indicates the start of a   pseudo-op.  If it is, then write out any unwritten instructions.  */voidd30v_start_line (){  char *c = input_line_pointer;  while (isspace (*c))    c++;  if (*c == '.')    d30v_cleanup (false);}static voidcheck_size (value, bits, file, line)     long value;     int bits;     char *file;     int line;{  int tmp, max;  if (value < 0)    tmp = ~value;  else    tmp = value;  max = (1 << (bits - 1)) - 1;  if (tmp > max)    as_bad_where (file, line, _("value too large to fit in %d bits"), bits);  return;}/* d30v_frob_label() is called when after a label is recognized.  */voidd30v_frob_label (lab)     symbolS *lab;{  /* Emit any pending instructions.  */  d30v_cleanup (false);  /* Update the label's address with the current output pointer.  */  symbol_set_frag (lab, frag_now);  S_SET_VALUE (lab, (valueT) frag_now_fix ());  /* Record this label for future adjustment after we find out what     kind of data it references, and the required alignment therewith.  */  d30v_last_label = lab;}/* Hook into cons for capturing alignment changes.  */voidd30v_cons_align (size)     int size;{  int log_size;  log_size = 0;  while ((size >>= 1) != 0)    ++log_size;  if (d30v_current_align < log_size)    d30v_align (log_size, (char *) NULL, NULL);  else if (d30v_current_align > log_size)    d30v_current_align = log_size;  d30v_last_label = NULL;}/* Called internally to handle all alignment needs.  This takes care   of eliding calls to frag_align if'n the cached current alignment   says we've already got it, as well as taking care of the auto-aligning   labels wrt code.  */static voidd30v_align (n, pfill, label)     int n;     char *pfill;     symbolS *label;{  /* The front end is prone to changing segments out from under us     temporarily when -g is in effect.  */  int switched_seg_p = (d30v_current_align_seg != now_seg);  /* Do not assume that if 'd30v_current_align >= n' and     '! switched_seg_p' that it is safe to avoid performing     this alignement request.  The alignment of the current frag     can be changed under our feet, for example by a .ascii     directive in the source code.  cf testsuite/gas/d30v/reloc.s  */  d30v_cleanup (false);  if (pfill == NULL)    {      if (n > 2	  && (bfd_get_section_flags (stdoutput, now_seg) & SEC_CODE) != 0)	{	  static char const nop[4] = { 0x00, 0xf0, 0x00, 0x00 };	  /* First, make sure we're on a four-byte boundary, in case	     someone has been putting .byte values the text section.  */	  if (d30v_current_align < 2 || switched_seg_p)	    frag_align (2, 0, 0);	  frag_align_pattern (n, nop, sizeof nop, 0);	}      else	frag_align (n, 0, 0);    }  else    frag_align (n, *pfill, 0);  if (!switched_seg_p)    d30v_current_align = n;  if (label != NULL)    {      symbolS     *sym;      int          label_seen = false;      struct frag *old_frag;      valueT       old_value;      valueT       new_value;      assert (S_GET_SEGMENT (label) == now_seg);      old_frag  = symbol_get_frag (label);      old_value = S_GET_VALUE (label);      new_value = (valueT) frag_now_fix ();      /* It is possible to have more than one label at a particular	 address, especially if debugging is enabled, so we must	 take care to adjust all the labels at this address in this	 fragment.  To save time we search from the end of the symbol	 list, backwards, since the symbols we are interested in are	 almost certainly the ones that were most recently added.	 Also to save time we stop searching once we have seen at least	 one matching label, and we encounter a label that is no longer	 in the target fragment.  Note, this search is guaranteed to	 find at least one match when sym == label, so no special case	 code is necessary.  */      for (sym = symbol_lastP; sym != NULL; sym = symbol_previous (sym))	{	  if (symbol_get_frag (sym) == old_frag	      && S_GET_VALUE (sym) == old_value)	    {	      label_seen = true;	      symbol_set_frag (sym, frag_now);	      S_SET_VALUE (sym, new_value);	    }	  else if (label_seen && symbol_get_frag (sym) != old_frag)	    break;	}    }  record_alignment (now_seg, n);}/* Handle the .align pseudo-op.  This aligns to a power of two.  We   hook here to latch the current alignment.  */static voids_d30v_align (ignore)     int ignore;{  int align;  char fill, *pfill = NULL;  long max_alignment = 15;  align = get_absolute_expression ();  if (align > max_alignment)    {      align = max_alignment;      as_warn (_("Alignment too large: %d assumed"), align);    }  else if (align < 0)    {      as_warn (_("Alignment negative: 0 assumed"));      align = 0;    }  if (*input_line_pointer == ',')    {      input_line_pointer++;      fill = get_absolute_expression ();      pfill = &fill;    }  d30v_last_label = NULL;  d30v_align (align, pfill, NULL);  demand_empty_rest_of_line ();}/* Handle the .text pseudo-op.  This is like the usual one, but it   clears the saved last label and resets known alignment.  */static voids_d30v_text (i)     int i;{  s_text (i);  d30v_last_label = NULL;  d30v_current_align = 0;  d30v_current_align_seg = now_seg;}/* Handle the .data pseudo-op.  This is like the usual one, but it   clears the saved last label and resets known alignment.  */static voids_d30v_data (i)     int i;{  s_data (i);  d30v_last_label = NULL;  d30v_current_align = 0;  d30v_current_align_seg = now_seg;}/* Handle the .section pseudo-op.  This is like the usual one, but it   clears the saved last label and resets known alignment.  */static voids_d30v_section (ignore)     int ignore;{  obj_elf_section (ignore);  d30v_last_label = NULL;  d30v_current_align = 0;  d30v_current_align_seg = now_seg;}

⌨️ 快捷键说明

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