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

📄 tc-cris.c

📁 基于4个mips核的noc设计
💻 C
📖 第 1 页 / 共 5 页
字号:
    /* We must have a '[' or it's a clean failure.  */    return 0;  /* Eat the first '['.  */  (*cPP)++;  if (**cPP == '[')    {      /* A second '[', so this must be double-indirect mode.  */      (*cPP)++;      prefixp->kind = PREFIX_DIP;      prefixp->opcode = DIP_OPCODE;      /* Get the register or fail entirely.  */      if (! get_gen_reg (cPP, &reg_number))	return 0;      else	{	  prefixp->opcode |= reg_number /* << 0 */ ;	  if (**cPP == '+')	    {	      /* Since we found a '+', this must be double-indirect		 autoincrement mode.  */	      (*cPP)++;	      prefixp->opcode |= AUTOINCR_BIT << 8;	    }	  /* There's nothing particular to do, if this was a	     double-indirect *without* autoincrement.  */	}      /* Check the first ']'.  The second one is checked at the end.  */      if (**cPP != ']')	return 0;      /* Eat the first ']', so we'll be looking at a second ']'.  */      (*cPP)++;    }  /* No second '['.  Then we should have a register here, making     it "[rN".  */  else if (get_gen_reg (cPP, &prefixp->base_reg_number))    {      /* This must be indexed or offset mode: "[rN+I]" or	 "[rN+rM.S]" or "[rN+[rM].S]" or "[rN+[rM+].S]".  */      if (**cPP == '+')	{	  /* Not the first alternative, must be one of the last	     three.  */	  int index_reg_number;	  (*cPP)++;	  if (**cPP == '[')	    {	      /* This is "[rx+["...  Expect a register next.  */	      int size_bits;	      (*cPP)++;	      if (!get_gen_reg (cPP, &index_reg_number))		return 0;	      prefixp->kind = PREFIX_BDAP;	      prefixp->opcode		= (BDAP_INDIR_OPCODE		   + (prefixp->base_reg_number << 12)		   + index_reg_number);	      /* We've seen "[rx+[ry", so check if this is		 autoincrement.  */	      if (**cPP == '+')		{		  /* Yep, now at "[rx+[ry+".  */		  (*cPP)++;		  prefixp->opcode |= AUTOINCR_BIT << 8;		}	      /* If it wasn't autoincrement, we don't need to		 add anything.  */	      /* Check a first closing ']': "[rx+[ry]" or		 "[rx+[ry+]".  */	      if (**cPP != ']')		return 0;	      (*cPP)++;	      /* Now expect a size modifier ".S".  */	      if (! get_bwd_size_modifier (cPP, &size_bits))		return 0;	      prefixp->opcode |= size_bits << 4;	      /* Ok, all interesting stuff has been seen:		 "[rx+[ry+].S" or "[rx+[ry].S".  We only need to		 expect a final ']', which we'll do in a common		 closing session.  */	    }	  /* Seen "[rN+", but not a '[', so check if we have a	     register.  */	  else if (get_gen_reg (cPP, &index_reg_number))	    {	      /* This is indexed mode: "[rN+rM.S]" or		 "[rN+rM.S+]".  */	      int size_bits;	      prefixp->kind = PREFIX_BIAP;	      prefixp->opcode		= (BIAP_OPCODE		   | prefixp->base_reg_number /* << 0 */		   | (index_reg_number << 12));	      /* Consume the ".S".  */	      if (! get_bwd_size_modifier (cPP, &size_bits))		/* Missing size, so fail.  */		return 0;	      else		/* Size found.  Add that piece and drop down to		   the common checking of the closing ']'.  */		prefixp->opcode |= size_bits << 4;	    }	  /* Seen "[rN+", but not a '[' or a register, so then	     it must be a constant "I".  */	  else if (cris_get_expression (cPP, &prefixp->expr))	    {	      /* Expression found, so fill in the bits of offset		 mode and drop down to check the closing ']'.  */	      prefixp->kind = PREFIX_BDAP_IMM;	    }	  else	    /* Nothing valid here: lose.  */	    return 0;	}      /* Seen "[rN" but no '+', so check if it's a '-'.  */      else if (**cPP == '-')	{	  /* Yep, we must have offset mode.  */	  if (! cris_get_expression (cPP, &prefixp->expr))	    /* No expression, so we lose.  */	    return 0;	  else	    {	      /* Expression found to make this offset mode, so		 fill those bits and drop down to check the		 closing ']'.  */	      prefixp->kind = PREFIX_BDAP_IMM;	    }	}      else	{	  /* We've seen "[rN", but not '+' or '-'; rather a ']'.	     Hmm.  Normally this is a simple indirect mode that we	     shouldn't match, but if we expect ']', then we have a	     zero offset, so it can be a three-address-operand,	     like "[rN],rO,rP", thus offset mode.	     Don't eat the ']', that will be done in the closing	     ceremony.  */	  prefixp->expr.X_op = O_constant;	  prefixp->expr.X_add_number = 0;	  prefixp->expr.X_add_symbol = NULL;	  prefixp->expr.X_op_symbol = NULL;	  prefixp->kind = PREFIX_BDAP_IMM;	}    }  /* A '[', but no second '[', and no register.  Check if we     have an expression, making this "[I]" for a double-indirect     prefix.  */  else if (cris_get_expression (cPP, &prefixp->expr))    {      /* Expression found, the so called absolute mode for a	 double-indirect prefix on PC.  */      prefixp->kind = PREFIX_DIP;      prefixp->opcode = DIP_OPCODE | (AUTOINCR_BIT << 8) | REG_PC;      prefixp->reloc = BFD_RELOC_32;    }  else    /* Neither '[' nor register nor expression.  We lose.  */    return 0;  /* We get here as a closing ceremony to a successful match.  We just     need to check the closing ']'.  */  if (**cPP != ']')    /* Oops.  Close but no air-polluter.  */    return 0;  /* Don't forget to consume that ']', before returning in glory.  */  (*cPP)++;  return 1;}/* Get an expression from the string pointed out by *cPP.   The pointer *cPP is advanced to the character following the expression   on a success, or retains its original value otherwise.   cPP	   Pointer to pointer to string beginning with the expression.   exprP   Pointer to structure containing the expression.   Return 1 iff a correct expression is found.  */static intcris_get_expression (cPP, exprP)     char **cPP;     expressionS *exprP;{  char *saved_input_line_pointer;  segT exp;  /* The "expression" function expects to find an expression at the     global variable input_line_pointer, so we have to save it to give     the impression that we don't fiddle with global variables.  */  saved_input_line_pointer = input_line_pointer;  input_line_pointer = *cPP;  exp = expression (exprP);  if (exprP->X_op == O_illegal || exprP->X_op == O_absent)    {      input_line_pointer = saved_input_line_pointer;      return 0;    }  /* Everything seems to be fine, just restore the global     input_line_pointer and say we're successful.  */  *cPP = input_line_pointer;  input_line_pointer = saved_input_line_pointer;  return 1;}/* Get a sequence of flag characters from *spp.  The pointer *cPP is   advanced to the character following the expression.	The flag   characters are consecutive, no commas or spaces.   cPP	     Pointer to pointer to string beginning with the expression.   flagp     Pointer to int to return the flags expression.   Return 1 iff a correct flags expression is found.  */static intget_flags (cPP, flagsp)     char **cPP;     int *flagsp;{  for (;;)    {      switch (**cPP)	{	case 'd':	case 'D':	case 'm':	case 'M':	  *flagsp |= 0x80;	  break;	case 'e':	case 'E':	case 'b':	case 'B':	  *flagsp |= 0x40;	  break;	case 'i':	case 'I':	  *flagsp |= 0x20;	  break;	case 'x':	case 'X':	  *flagsp |= 0x10;	  break;	case 'n':	case 'N':	  *flagsp |= 0x8;	  break;	case 'z':	case 'Z':	  *flagsp |= 0x4;	  break;	case 'v':	case 'V':	  *flagsp |= 0x2;	  break;	case 'c':	case 'C':	  *flagsp |= 1;	  break;	default:	  /* We consider this successful if we stop at a comma or	     whitespace.  Anything else, and we consider it a failure.  */	  if (**cPP != ','	      && **cPP != 0	      && ! isspace (**cPP))	    return 0;	  else	    return 1;	}      /* Don't forget to consume each flag character.  */      (*cPP)++;    }}/* Generate code and fixes for a BDAP prefix.   base_regno	Int containing the base register number.   exprP	Pointer to structure containing the offset expression.  */static voidgen_bdap (base_regno, exprP)     int base_regno;     expressionS *exprP;{  unsigned int opcode;  char *opcodep;  /* Put out the prefix opcode; assume quick immediate mode at first.  */  opcode = BDAP_QUICK_OPCODE | (base_regno << 12);  opcodep = cris_insn_first_word_frag ();  md_number_to_chars (opcodep, opcode, 2);  if (exprP->X_op == O_constant)    {      /* We have an absolute expression that we know the size of right	 now.  */      long int value;      int size;      value = exprP->X_add_number;      if (value < -32768 || value > 32767)	/* Outside range for a "word", make it a dword.  */	size = 2;      else	/* Assume "word" size.  */	size = 1;      /* If this is a signed-byte value, we can fit it into the prefix	 insn itself.  */      if (value >= -128 && value <= 127)	opcodep[0] = value;      else	{	  /* This is a word or dword displacement, which will be put in a	     word or dword after the prefix.  */	  char *p;	  opcodep[0] = BDAP_PC_LOW + (size << 4);	  opcodep[1] &= 0xF0;	  opcodep[1] |= BDAP_INCR_HIGH;	  p = frag_more (1 << size);	  md_number_to_chars (p, value, 1 << size);	}    }  else    /* The expression is not defined yet but may become absolute.  We make       it a relocation to be relaxed.  */    frag_var (rs_machine_dependent, 4, 0,	      ENCODE_RELAX (STATE_BASE_PLUS_DISP_PREFIX, STATE_UNDF),	      exprP->X_add_symbol, exprP->X_add_number, opcodep);}/* Encode a branch displacement in the range -256..254 into the form used   by CRIS conditional branch instructions.   offset  The displacement value in bytes.  */static intbranch_disp (offset)     int offset;{  int disp;  disp = offset & 0xFE;  if (offset < 0)    disp |= 1;  return disp;}/* Generate code and fixes for a 32-bit conditional branch instruction   created by "extending" an existing 8-bit branch instruction.   opcodep    Pointer to the word containing the original 8-bit branch	      instruction.   writep     Pointer to "extension area" following the first instruction	      word.   fragP      Pointer to the frag containing the instruction.   add_symP,  Parts of the destination address expression.   sub_symP,   add_num.  */static voidgen_cond_branch_32 (opcodep, writep, fragP, add_symP, sub_symP, add_num)     char *opcodep;     char *writep;     fragS *fragP;     symbolS *add_symP;     symbolS *sub_symP;     long int add_num;{  if (warn_for_branch_expansion)    {      /* FIXME: Find out and change to as_warn_where.  Add testcase.  */      as_warn (_("32-bit conditional branch generated"));    }  /* Here, writep points to what will be opcodep + 2.  First, we change     the actual branch in opcodep[0] and opcodep[1], so that in the     final insn, it will look like:       opcodep+10: Bcc .-6     This means we don't have to worry about changing the opcode or     messing with te delay-slot instruction.  So, we move it to last in     the "extended" branch, and just change the displacement.  Admittedly,     it's not the optimal extended construct, but we should get this     rarely enough that it shouldn't matter.  */  writep[8] = branch_disp (-2 - 6);  writep[9] = opcodep[1];  /* Then, we change the branch to an unconditional branch over the     extended part, to the new location of the Bcc:       opcodep:	  BA .+10       opcodep+2: NOP     Note that these two writes are to currently different locations,     merged later.  */  md_number_to_chars (opcodep, BA_QUICK_OPCODE + 8, 2);  md_number_to_chars (writep, NOP_OPCODE, 2);  /* Then the extended thing, the 32-bit jump insn.       opcodep+4: JUMP [PC+]  */  md_number_to_chars (writep + 2, JUMP_PC_INCR_OPCODE, 2);  /* We have to fill in the actual value too.       opcodep+6: .DWORD     This is most probably an expression, but we can cope with an absolute     value too.  FIXME: Testcase needed.  */  if (add_symP == NULL && sub_symP == NULL)    /* An absolute address.  */    md_number_to_chars (writep + 4, add_num, 4);  else    {      /* Not absolute, we have to make it a frag for later evaluation.  */      know (sub_symP == 0);      fix_new (fragP, writep + 4 - fragP->fr_literal, 4, add_symP,	       add_num, 0, BFD_RELOC_32);    }}/* This *could* be:   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.   type	  A character from FLTCHARS that describes what kind of	  floating-point number is wanted.   litp	  A pointer to an array that the result should be stored in.   sizep  A pointer to an integer where the size of the result is stored.   But we don't support floating point constants in assembly code *at all*,   since it's suboptimal and just opens up bug opportunities.  GCC emits   the bit patterns as hex.  All we could do here is to emit what GCC   would have done in the first place.	*Nobody* writes floating-point   code a

⌨️ 快捷键说明

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