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

📄 tc-cris.c

📁 基于4个mips核的noc设计
💻 C
📖 第 1 页 / 共 5 页
字号:
      out_insnp->opcode = instruction->match;      out_insnp->reloc = BFD_RELOC_NONE;      out_insnp->insn_type = CRIS_INSN_NORMAL;      out_insnp->imm_oprnd_size = 0;      imm_expr_found = 0;      /* Build the opcode, checking as we go to make sure that the	 operands match.  */      for (args = instruction->args;; ++args)	{	  switch (*args)	    {	    case '\0':	      /* If we've come to the end of arguments, we're done.  */	      if (*s == '\0')		match = 1;	      break;	    case '!':	      /* Non-matcher character for disassembly.		 Ignore it here.  */	      continue;	    case ',':	    case ' ':	      /* These must match exactly.  */	      if (*s++ == *args)		continue;	      break;	    case 'B':	      /* This is not really an operand, but causes a "BDAP		 -size,SP" prefix to be output, for PUSH instructions.  */	      prefixp->kind = PREFIX_PUSH;	      continue;	    case 'b':	      /* This letter marks an operand that should not be matched		 in the assembler. It is a branch with 16-bit		 displacement.  The assembler will create them from the		 8-bit flavor when necessary.  The assembler does not		 support the [rN+] operand, as the [r15+] that is		 generated for 16-bit displacements.  */	      break;	    case 'c':	      /* A 5-bit unsigned immediate in bits <4:0>.  */	      if (! cris_get_expression (&s, &out_insnp->expr))		break;	      else		{		  if (out_insnp->expr.X_op == O_constant		      && (out_insnp->expr.X_add_number < 0			  || out_insnp->expr.X_add_number > 31))		    as_bad (_("Immediate value not in 5 bit unsigned range: %ld"),			    out_insnp->expr.X_add_number);		  out_insnp->reloc = BFD_RELOC_CRIS_UNSIGNED_5;		  continue;		}	    case 'C':	      /* A 4-bit unsigned immediate in bits <3:0>.  */	      if (! cris_get_expression (&s, &out_insnp->expr))		break;	      else		{		  if (out_insnp->expr.X_op == O_constant		      && (out_insnp->expr.X_add_number < 0			  || out_insnp->expr.X_add_number > 15))		    as_bad (_("Immediate value not in 4 bit unsigned range: %ld"),			    out_insnp->expr.X_add_number);		  out_insnp->reloc = BFD_RELOC_CRIS_UNSIGNED_4;		  continue;		}	    case 'D':	      /* General register in bits <15:12> and <3:0>.  */	      if (! get_gen_reg (&s, &regno))		break;	      else		{		  out_insnp->opcode |= regno /* << 0 */;		  out_insnp->opcode |= regno << 12;		  continue;		}	    case 'f':	      /* Flags from the condition code register.  */	      {		int flags = 0;		if (! get_flags (&s, &flags))		  break;		out_insnp->opcode |= ((flags & 0xf0) << 8) | (flags & 0xf);		continue;	      }	    case 'i':	      /* A 6-bit signed immediate in bits <5:0>.  */	      if (! cris_get_expression (&s, &out_insnp->expr))		break;	      else		{		  if (out_insnp->expr.X_op == O_constant		      && (out_insnp->expr.X_add_number < -32			  || out_insnp->expr.X_add_number > 31))		    as_bad (_("Immediate value not in 6 bit range: %ld"),			    out_insnp->expr.X_add_number);		  out_insnp->reloc = BFD_RELOC_CRIS_SIGNED_6;		  continue;		}	    case 'I':	      /* A 6-bit unsigned immediate in bits <5:0>.  */	      if (! cris_get_expression (&s, &out_insnp->expr))		break;	      else		{		  if (out_insnp->expr.X_op == O_constant		      && (out_insnp->expr.X_add_number < 0			  || out_insnp->expr.X_add_number > 63))		    as_bad (_("Immediate value not in 6 bit unsigned range: %ld"),			    out_insnp->expr.X_add_number);		  out_insnp->reloc = BFD_RELOC_CRIS_UNSIGNED_6;		  continue;		}	    case 'M':	      /* A size modifier, B, W or D, to be put in a bit position		 suitable for CLEAR instructions (i.e. reflecting a zero		 register).  */	      if (! get_bwd_size_modifier (&s, &size_bits))		break;	      else		{		  switch (size_bits)		    {		    case 0:		      out_insnp->opcode |= 0 << 12;		      break;		    case 1:		      out_insnp->opcode |= 4 << 12;		      break;		    case 2:		      out_insnp->opcode |= 8 << 12;		      break;		    }		  continue;		}	    case 'm':	      /* A size modifier, B, W or D, to be put in bits <5:4>.  */	      if (! get_bwd_size_modifier (&s, &size_bits))		break;	      else		{		  out_insnp->opcode |= size_bits << 4;		  continue;		}	    case 'o':	      /* A branch expression.  */	      if (! cris_get_expression (&s, &out_insnp->expr))		break;	      else		{		  out_insnp->insn_type = CRIS_INSN_BRANCH;		  continue;		}	    case 'O':	      /* A BDAP expression for any size, "expr,r".  */	      if (! cris_get_expression (&s, &prefixp->expr))		break;	      else		{		  if (*s != ',')		    break;		  s++;		  if (!get_gen_reg (&s, &prefixp->base_reg_number))		    break;		  /* Since 'O' is used with an explicit bdap, we have no		     "real" instruction.  */		  prefixp->kind = PREFIX_BDAP_IMM;		  out_insnp->insn_type = CRIS_INSN_NONE;		  continue;		}	    case 'P':	      /* Special register in bits <15:12>.  */	      if (! get_spec_reg (&s, &out_insnp->spec_reg))		break;	      else		{		  /* Use of some special register names come with a		     specific warning.	Note that we have no ".cpu type"		     pseudo yet, so some of this is just unused		     framework.  */		  if (out_insnp->spec_reg->warning)		    as_warn (out_insnp->spec_reg->warning);		  else if (out_insnp->spec_reg->applicable_version			   == cris_ver_warning)		    /* Others have a generic warning.  */		    as_warn (_("Unimplemented register `%s' specified"),			     out_insnp->spec_reg->name);		  out_insnp->opcode		    |= out_insnp->spec_reg->number << 12;		  continue;		}	    case 'p':	      /* This character is used in the disassembler to		 recognize a prefix instruction to fold into the		 addressing mode for the next instruction.  It is		 ignored here.  */	      continue;	    case 'R':	      /* General register in bits <15:12>.  */	      if (! get_gen_reg (&s, &regno))		break;	      else		{		  out_insnp->opcode |= regno << 12;		  continue;		}	    case 'r':	      /* General register in bits <3:0>.  */	      if (! get_gen_reg (&s, &regno))		break;	      else		{		  out_insnp->opcode |= regno /* << 0 */;		  continue;		}	    case 'S':	      /* Source operand in bit <10> and a prefix; a 3-operand		 prefix.  */	      if (! get_3op_or_dip_prefix_op (&s, prefixp))		break;	      else		continue;	    case 's':	      /* Source operand in bits <10>, <3:0> and optionally a		 prefix; i.e. an indirect operand or an side-effect		 prefix.  */	      if (! get_autoinc_prefix_or_indir_op (&s, prefixp, &mode,						    &regno,						    &imm_expr_found,						    &out_insnp->expr))		break;	      else		{		  if (prefixp->kind != PREFIX_NONE)		    {		      /* A prefix, so it has the autoincrement bit			 set.  */		      out_insnp->opcode |= (AUTOINCR_BIT << 8);		    }		  else		    /* No prefix.  The "mode" variable contains bits like		       whether or not this is autoincrement mode.  */		    out_insnp->opcode |= (mode << 10);		  out_insnp->opcode |= regno /* << 0 */ ;		  continue;		}	    case 'x':	      /* Rs.m in bits <15:12> and <5:4>.  */	      if (! get_gen_reg (&s, &regno)		  || ! get_bwd_size_modifier (&s, &size_bits))		break;	      else		{		  out_insnp->opcode |= (regno << 12) | (size_bits << 4);		  continue;		}	    case 'y':	      /* Source operand in bits <10>, <3:0> and optionally a		 prefix; i.e. an indirect operand or an side-effect		 prefix.		 The difference to 's' is that this does not allow an		 "immediate" expression.  */	      if (! get_autoinc_prefix_or_indir_op (&s, prefixp,						    &mode, &regno,						    &imm_expr_found,						    &out_insnp->expr)		  || imm_expr_found)		break;	      else		{		  if (prefixp->kind != PREFIX_NONE)		    {		      /* A prefix, and those matched here always have			 side-effects (see 's' case).  */		      out_insnp->opcode |= (AUTOINCR_BIT << 8);		    }		  else		    {		      /* No prefix.  The "mode" variable contains bits			 like whether or not this is autoincrement			 mode.  */		      out_insnp->opcode |= (mode << 10);		    }		  out_insnp->opcode |= regno /* << 0 */;		  continue;		}	    case 'z':	      /* Size modifier (B or W) in bit <4>.  */	      if (! get_bw_size_modifier (&s, &size_bits))		break;	      else		{		  out_insnp->opcode |= size_bits << 4;		  continue;		}	    default:	      BAD_CASE (*args);	    }	  /* We get here when we fail a match above or we found a	     complete match.  Break out of this loop.  */	  break;	}      /* Was it a match or a miss?  */      if (match == 0)	{	  /* If it's just that the args don't match, maybe the next	     item in the table is the same opcode but with	     matching operands.  */	  if (instruction[1].name != NULL	      && ! strcmp (instruction->name, instruction[1].name))	    {	      /* Yep.  Restart and try that one instead.  */	      ++instruction;	      s = operands;	      continue;	    }	  else	    {	      /* We've come to the end of instructions with this		 opcode, so it must be an error.  */	      as_bad (_("Illegal operands"));	      return;	    }	}      else	{	  /* We have a match.  Check if there's anything more to do.  */	  if (imm_expr_found)	    {	      /* There was an immediate mode operand, so we must check		 that it has an appropriate size.  */	      switch (instruction->imm_oprnd_size)		{		default:		case SIZE_NONE:		  /* Shouldn't happen; this one does not have immediate		     operands with different sizes.  */		  BAD_CASE (instruction->imm_oprnd_size);		  break;		case SIZE_FIX_32:		  out_insnp->imm_oprnd_size = 4;		  break;		case SIZE_SPEC_REG:		  switch (out_insnp->spec_reg->reg_size)		    {		    case 1:		      if (out_insnp->expr.X_op == O_constant			  && (out_insnp->expr.X_add_number < -128			      || out_insnp->expr.X_add_number > 255))			as_bad (_("Immediate value not in 8 bit range: %ld"),				out_insnp->expr.X_add_number);		      /* Fall through.  */		    case 2:		      /* FIXME:  We need an indicator in the instruction			 table to pass on, to indicate if we need to check			 overflow for a signed or unsigned number.  */		      if (out_insnp->expr.X_op == O_constant			  && (out_insnp->expr.X_add_number < -32768			      || out_insnp->expr.X_add_number > 65535))			as_bad (_("Immediate value not in 16 bit range: %ld"),				out_insnp->expr.X_add_number);		      out_insnp->imm_oprnd_size = 2;		      break;		    case 4:		      out_insnp->imm_oprnd_size = 4;		      break;		    default:		      BAD_CASE (out_insnp->spec_reg->reg_size);		    }		  break;		case SIZE_FIELD:		  switch (size_bits)		    {		    case 0:		      if (out_insnp->expr.X_op == O_constant			  && (out_insnp->expr.X_add_number < -128			      || out_insnp->expr.X_add_number > 255))			as_bad (_("Immediate value not in 8 bit range: %ld"),				out_insnp->expr.X_add_number);		      /* Fall through.  */		    case 1:		      if (out_insnp->expr.X_op == O_constant			  && (out_insnp->expr.X_add_number < -32768			      || out_insnp->expr.X_add_number > 65535))			as_bad (_("Immediate value not in 16 bit range: %ld"),				out_insnp->expr.X_add_number);		      out_insnp->imm_oprnd_size = 2;		      break;		    case 2:		      out_insnp->imm_oprnd_size = 4;		      break;		    default:		      BAD_CASE (out_insnp->spec_reg->reg_size);		    }		}	    }	}      break;    }}/* Get a B, W, or D size modifier from the string pointed out by *cPP,   which must point to a '.' in front of the modifier.	On successful   return, *cPP is advanced to the character following the size   modifier, and is undefined otherwise.   cPP		Pointer to pointer to string starting		with the size modifier.   size_bitsp	Pointer to variable to contain the size bits on		successful return.   Return 1 iff a correct size modifier is found, else 0.  */static intget_bwd_size_modifier (cPP, size_bitsp)     char **cPP;     int *size_bitsp;{  if (**cPP != '.')    return 0;  else    {      /* Consume the '.'.  */      (*cPP)++;      switch (**cPP)	{	case 'B':	case 'b':

⌨️ 快捷键说明

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