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

📄 tc-d10v.c

📁 基于4个mips核的noc设计
💻 C
📖 第 1 页 / 共 3 页
字号:
    str++;  /* Find the opcode end.  */  for (op_start = op_end = (unsigned char *) (str);       *op_end       && nlen < 20       && !is_end_of_line[*op_end] && *op_end != ' ';       op_end++)    {      name[nlen] = tolower (op_start[nlen]);      nlen++;    }  name[nlen] = 0;  if (nlen == 0)    return -1;  /* Find the first opcode with the proper name.  */  *opcode = (struct d10v_opcode *) hash_find (d10v_hash, name);  if (*opcode == NULL)    as_fatal (_("unknown opcode: %s"), name);  save = input_line_pointer;  input_line_pointer = op_end;  *opcode = find_opcode (*opcode, myops);  if (*opcode == 0)    return -1;  input_line_pointer = save;  insn = build_insn ((*opcode), myops, 0);  return (insn);}/* Find the symbol which has the same name as the register in EXP.  */static symbolS *find_symbol_matching_register (exp)     expressionS *exp;{  int i;  if (exp->X_op != O_register)    return NULL;  /* Find the name of the register.  */  for (i = d10v_reg_name_cnt (); i--;)    if (d10v_predefined_registers[i].value == exp->X_add_number)      break;  if (i < 0)    abort ();  /* Now see if a symbol has been defined with the same name.  */  return symbol_find (d10v_predefined_registers[i].name);}/* Get a pointer to an entry in the opcode table.   The function must look at all opcodes with the same name and use   the operands to choose the correct opcode.  */static struct d10v_opcode *find_opcode (opcode, myops)     struct d10v_opcode *opcode;     expressionS myops[];{  int i, match;  struct d10v_opcode *next_opcode;  /* Get all the operands and save them as expressions.  */  get_operands (myops);  /* Now see if the operand is a fake.  If so, find the correct size     instruction, if possible.  */  if (opcode->format == OPCODE_FAKE)    {      int opnum = opcode->operands[0];      int flags;      if (myops[opnum].X_op == O_register)	{	  myops[opnum].X_op = O_symbol;	  myops[opnum].X_add_symbol =	    symbol_find_or_make ((char *) myops[opnum].X_op_symbol);	  myops[opnum].X_add_number = 0;	  myops[opnum].X_op_symbol = NULL;	}      next_opcode = opcode + 1;      /* If the first operand is supposed to be a register, make sure	 we got a valid one.  */      flags = d10v_operands[next_opcode->operands[0]].flags;      if (flags & OPERAND_REG)	{	  int X_op = myops[0].X_op;	  int num = myops[0].X_add_number;	  if (X_op != O_register	      || (num & ~flags		  & (OPERAND_GPR | OPERAND_ACC0 | OPERAND_ACC1		     | OPERAND_FFLAG | OPERAND_CFLAG | OPERAND_CONTROL)))	    {	      as_bad (_("bad opcode or operands"));	      return 0;	    }	}      if (myops[opnum].X_op == O_constant	  || (myops[opnum].X_op == O_symbol	      && S_IS_DEFINED (myops[opnum].X_add_symbol)	      && (S_GET_SEGMENT (myops[opnum].X_add_symbol) == now_seg)))	{	  for (i = 0; opcode->operands[i + 1]; i++)	    {	      int bits = d10v_operands[next_opcode->operands[opnum]].bits;	      int flags = d10v_operands[next_opcode->operands[opnum]].flags;	      if (flags & OPERAND_ADDR)		bits += 2;	      if (myops[opnum].X_op == O_constant)		{		  if (!check_range (myops[opnum].X_add_number, bits, flags))		    return next_opcode;		}	      else		{		  fragS *sym_frag;		  fragS *f;		  unsigned long current_position;		  unsigned long symbol_position;		  unsigned long value;		  boolean found_symbol;		  /* Calculate the address of the current instruction		     and the address of the symbol.  Do this by summing		     the offsets of previous frags until we reach the		     frag containing the symbol, and the current frag.  */		  sym_frag = symbol_get_frag (myops[opnum].X_add_symbol);		  found_symbol = false;		  current_position =		    obstack_next_free (&frchain_now->frch_obstack)		    - frag_now->fr_literal;		  symbol_position = S_GET_VALUE (myops[opnum].X_add_symbol);		  for (f = frchain_now->frch_root; f; f = f->fr_next)		    {		      current_position += f->fr_fix + f->fr_offset;		      if (f == sym_frag)			found_symbol = true;		      if (! found_symbol)			symbol_position += f->fr_fix + f->fr_offset;		    }		  value = symbol_position;		  if (flags & OPERAND_ADDR)		    value -= current_position;		  if (AT_WORD_P (&myops[opnum]))		    {		      if (bits > 4)			{			  bits += 2;			  if (!check_range (value, bits, flags))			    return next_opcode;			}		    }		  else if (!check_range (value, bits, flags))		    return next_opcode;		}	      next_opcode++;	    }	  as_fatal (_("value out of range"));	}      else	{	  /* Not a constant, so use a long instruction.  */	  return opcode + 2;	}    }  else    {      match = 0;      /* Now search the opcode table table for one with operands	 that matches what we've got.  */      while (!match)	{	  match = 1;	  for (i = 0; opcode->operands[i]; i++)	    {	      int flags = d10v_operands[opcode->operands[i]].flags;	      int X_op = myops[i].X_op;	      int num = myops[i].X_add_number;	      if (X_op == 0)		{		  match = 0;		  break;		}	      if (flags & OPERAND_REG)		{		  if ((X_op != O_register)		      || (num & ~flags			  & (OPERAND_GPR | OPERAND_ACC0 | OPERAND_ACC1			     | OPERAND_FFLAG | OPERAND_CFLAG			     | OPERAND_CONTROL)))		    {		      match = 0;		      break;		    }		}	      if (((flags & OPERAND_MINUS)   && ((X_op != O_absent) || (num != OPERAND_MINUS))) ||		  ((flags & OPERAND_PLUS)    && ((X_op != O_absent) || (num != OPERAND_PLUS))) ||		  ((flags & OPERAND_ATMINUS) && ((X_op != O_absent) || (num != OPERAND_ATMINUS))) ||		  ((flags & OPERAND_ATPAR)   && ((X_op != O_absent) || (num != OPERAND_ATPAR))) ||		  ((flags & OPERAND_ATSIGN)  && ((X_op != O_absent) || ((num != OPERAND_ATSIGN) && (num != OPERAND_ATPAR)))))		{		  match = 0;		  break;		}	      /* Unfortunatly, for the indirect operand in		 instructions such as ``ldb r1, @(c,r14)'' this		 function can be passed X_op == O_register (because		 'c' is a valid register name).  However we cannot		 just ignore the case when X_op == O_register but		 flags & OPERAND_REG is null, so we check to see if a		 symbol of the same name as the register exists.  If		 the symbol does exist, then the parser was unable to		 distinguish the two cases and we fix things here.		 (Ref: PR14826)  */	      if (!(flags & OPERAND_REG) && (X_op == O_register))		{		  symbolS *sym = find_symbol_matching_register (&myops[i]);		  if (sym != NULL)		    {		      myops[i].X_op = X_op = O_symbol;		      myops[i].X_add_symbol = sym;		    }		  else		    as_bad		      (_("illegal operand - register name found where none expected"));		}	    }	  /* We're only done if the operands matched so far AND there	     are no more to check.  */	  if (match && myops[i].X_op == 0)	    break;	  else	    match = 0;	  next_opcode = opcode + 1;	  if (next_opcode->opcode == 0)	    break;	  if (strcmp (next_opcode->name, opcode->name))	    break;	  opcode = next_opcode;	}    }  if (!match)    {      as_bad (_("bad opcode or operands"));      return (0);    }  /* Check that all registers that are required to be even are.     Also, if any operands were marked as registers, but were really symbols,     fix that here.  */  for (i = 0; opcode->operands[i]; i++)    {      if ((d10v_operands[opcode->operands[i]].flags & OPERAND_EVEN) &&	  (myops[i].X_add_number & 1))	as_fatal (_("Register number must be EVEN"));      if (myops[i].X_op == O_register)	{	  if (!(d10v_operands[opcode->operands[i]].flags & OPERAND_REG))	    {	      myops[i].X_op = O_symbol;	      myops[i].X_add_symbol =		symbol_find_or_make ((char *) myops[i].X_op_symbol);	      myops[i].X_add_number = 0;	      myops[i].X_op_symbol = NULL;	    }	}    }  return opcode;}/* 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 ATTRIBUTE_UNUSED;     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;    }  if (fixp->fx_r_type == BFD_RELOC_VTABLE_INHERIT      || fixp->fx_r_type == BFD_RELOC_VTABLE_ENTRY)    reloc->address = fixp->fx_offset;  reloc->addend = fixp->fx_addnumber;  return reloc;}intmd_estimate_size_before_relax (fragp, seg)     fragS *fragp ATTRIBUTE_UNUSED;     asection *seg ATTRIBUTE_UNUSED;{  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 ATTRIBUTE_UNUSED;{  char *where;  unsigned long insn;  long value;  int op_type;  int left = 0;  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"));	    }	}    }  op_type = fixp->fx_r_type;  if (op_type & 2048)    {      op_type -= 2048;      if (op_type & 1024)	{	  op_type -= 1024;	  fixp->fx_r_type = BFD_RELOC_D10V_10_PCREL_L;	  left = 1;	}      else if (op_type & 4096)	{	  op_type -= 4096;	  fixp->fx_r_type = BFD_RELOC_D10V_18;	}      else	fixp->fx_r_type =	  get_reloc ((struct d10v_operand *) &d10v_operands[op_type]);    }  /* 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_D10V_10_PCREL_L:    case BFD_RELOC_D10V_10_PCREL_R:    case BFD_RELOC_D10V_18_PCREL:    case BFD_RELOC_D10V_18:      /* Instruction addresses are always right-shifted by 2.  */      value >>= AT_WORD_RIGHT_SHIFT;      if (fixp->fx_size == 2)	bfd_putb16 ((bfd_vma) value, (unsigned char *) where);      else	{	  struct d10v_opcode *rep, *repi;	  rep = (struct d10v_opcode *) hash_find (d10v_hash, "rep");	  repi = (struct d10v_opcode *) hash_find (d10v_hash, "repi");	  if ((insn & FM11) == FM11	      && (  (repi != NULL && (insn & repi->mask) == (unsigned) repi->opcode)		  || (rep != NULL && (insn & rep->mask) == (unsigned) rep->opcode))	      && value < 4)	    as_fatal	      (_("line %d: rep or repi must include at least 4 instructions"),	       fixp->fx_line);	  insn =	    d10v_insert_operand (insn, op_type, (offsetT) value, left, fixp);	  bfd_putb32 ((bfd_vma) insn, (unsigned char *) where);	}      break;    case BFD_RELOC_32:      bfd_putb32 ((bfd_vma) value, (unsigned char *) where);      break;    case BFD_RELOC_16:      bfd_putb16 ((bfd_vma) value, (unsigned char *) where);      break;    case BFD_RELOC_VTABLE_INHERIT:    case BFD_RELOC_VTABLE_ENTRY:      fixp->fx_done = 0;      return 1;    default:      as_fatal (_("line %d: unknown relocation type: 0x%x"),		fixp->fx_line, fixp->fx_r_type);    }  return 0;}/* d10v_cleanup() is called after the assembler has finished parsing   the input file, when a label is read from the input file, or when a   stab directive is output.  Because the D10V 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   to be written.   NOTE: accesses a global, etype.   NOTE: invoked by various macros such as md_cleanup: see.  */intd10v_cleanup (){  segT seg;  subsegT subseg;  /* If cleanup was invoked because the assembler encountered, e.g., a     user label, we write out the pending instruction, if any.  If it     was invoked because the assembler is outputting a piece of line     debugging information, though, we write out the pending     instruction only if the --no-gstabs-packing command line switch     has been specified.  */  if (prev_opcode      && etype == PACK_UNSPEC      && (! outputting_stabs_line_debug || ! flag_allow_gstabs_packing))    {      seg = now_seg;      subseg = now_subseg;      if (prev_seg)	subseg_set (prev_seg, prev_subseg);      write_1_short (prev_opcode, prev_insn, fixups->next);      subseg_set (seg, subseg);      prev_opcode = NULL;    }  return 1;}/* Like normal .word, except support @word.  *//* Clobbers input_line_pointer, checks end-of-line.  */static voidd10v_dot_word (dummy)     int dummy ATTRIBUTE_UNUSED;{  expressionS exp;  char *p;  if (is_it_end_of_statement ())    {      demand_empty_rest_of_line ();      return;    }  do    {      expression (&exp);      if (!strncasecmp (input_line_pointer, "@word", 5))	{	  exp.X_add_number = 0;	  input_line_pointer += 5;	  p = frag_more (2);	  fix_new_exp (frag_now, p - frag_now->fr_literal, 2,		       &exp, 0, BFD_RELOC_D10V_18);	}      else	emit_expr (&exp, 2);    }  while (*input_line_pointer++ == ',');  input_line_pointer--;		/* Put terminator back into stream.  */  demand_empty_rest_of_line ();}/* Mitsubishi asked that we support some old syntax that apparently   had immediate operands starting with '#'.  This is in some of their   sample code but is not documented (although it appears in some   examples in their assembler manual). For now, we'll solve this   compatibility problem by simply ignoring any '#' at the beginning   of an operand.  *//* Operands that begin with '#' should fall through to here.  *//* From expr.c.  */voidmd_operand (expressionP)     expressionS *expressionP;{  if (*input_line_pointer == '#' && ! do_not_ignore_hash)    {      input_line_pointer++;      expression (expressionP);    }}booleand10v_fix_adjustable (fixP)     fixS *fixP;{  if (fixP->fx_addsy == NULL)    return 1;  /* Prevent all adjustments to global symbols.  */  if (S_IS_EXTERN (fixP->fx_addsy))    return 0;  if (S_IS_WEAK (fixP->fx_addsy))    return 0;  /* We need the symbol name for the VTABLE entries.  */  if (fixP->fx_r_type == BFD_RELOC_VTABLE_INHERIT      || fixP->fx_r_type == BFD_RELOC_VTABLE_ENTRY)    return 0;  return 1;}intd10v_force_relocation (fixp)     fixS *fixp;{  if (fixp->fx_r_type == BFD_RELOC_VTABLE_INHERIT      || fixp->fx_r_type == BFD_RELOC_VTABLE_ENTRY)    return 1;  return 0;}

⌨️ 快捷键说明

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