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

📄 tc-tahoe.c

📁 基于4个mips核的noc设计
💻 C
📖 第 1 页 / 共 4 页
字号:
	  titP->tit_error = _("Unknown operator");	  count = 0;	  titP->tit_opcode = 0;	}      else	{	  /*       * We found a match! So let's pick up as many operands as the       * instruction wants, and even gripe if there are too many.       * We expect comma to seperate each operand.       * We let instring track the text, while p tracks a part of the       * struct tot.       */	  count = 0;		/* no operands seen yet */	  instring = p + (*p != '\0');	/* point past the operation code */	  /* tip_op() screws with the input_line_pointer, so save it before	 I jump in */	  save_input_line_pointer = input_line_pointer;	  for (p = twP->args, operandp = titP->tit_operand;	       !*alloperr && *p;	       operandp++, p += 2)	    {	      /*	 * Here to parse one operand. Leave instring pointing just	 * past any one ',' that marks the end of this operand.	 */	      if (!p[1])		as_fatal (_("Compiler bug: ODD number of bytes in arg structure %s."),			  twP->args);	      else if (*instring)		{		  for (q = instring; (*q != ',' && *q != '\0'); q++)		    {		      if (*q == '\'' && q[1] != '\0')	/* Jump quoted characters */			q++;		    }		  c = *q;		  /*	   * Q points to ',' or '\0' that ends argument. C is that	   * character.	   */		  *q = '\0';		  operandp->top_access = p[0];		  operandp->top_width = p[1];		  tip_op (instring - 1, operandp);		  *q = c;	/* Restore input text.  */		  if (*(operandp->top_error))		    {		      alloperr = operandp->top_error;		    }		  instring = q + (c ? 1 : 0);	/* next operand (if any) */		  count++;	/*  won another argument, may have an operr */		}	      else		alloperr = _("Not enough operands");	    }	  /* Restore the pointer.  */	  input_line_pointer = save_input_line_pointer;	  if (!*alloperr)	    {	      if (*instring == ' ')		instring++;	/* Skip whitespace.  */	      if (*instring)		alloperr = _("Too many operands");	    }	  titP->tit_error = alloperr;	}    }  titP->tit_opcode = twP->code;	/* The op-code.  */  titP->tit_operands = count;}				/* tip *//* md_assemble() emit frags for 1 instruction */voidmd_assemble (instruction_string)     char *instruction_string;	/* A string: assemble 1 instruction.  */{  char *p;  register struct top *operandP;/* An operand. Scans all operands.  */  /*  char c_save;	fixme: remove this line *//* What used to live after an expression.  */  /*  struct frag *fragP;	fixme: remove this line *//* Fragment of code we just made.  */  /*  register struct top *end_operandP; fixme: remove this line *//* -> slot just after last operand					Limit of the for (each operand).  */  register expressionS *expP;	/* -> expression values for this operand */  /* These refer to an instruction operand expression.  */  segT to_seg;			/* Target segment of the address.	 */  register valueT this_add_number;  register symbolS *this_add_symbol;	/* +ve (minuend) symbol.  */  /*  tahoe_opcodeT opcode_as_number; fixme: remove this line *//* The opcode as a number.  */  char *opcodeP;		/* Where it is in a frag.  */  /*  char *opmodeP;	fixme: remove this line *//* Where opcode type is, in a frag.  */  int dispsize;			/* From top_dispsize: tahoe_operand_width				   (in bytes) */  int is_undefined;		/* 1 if operand expression's				   segment not known yet.  */  int pc_rel;			/* Is this operand pc relative? */  /* Decode the operand.  */  tip (&t, instruction_string);  /*   * Check to see if this operand decode properly.   * Notice that we haven't made any frags yet.   * If it goofed, then this instruction will wedge in any pass,   * and we can safely flush it, without causing interpass symbol phase   * errors. That is, without changing label values in different passes.   */  if (*t.tit_error)    {      as_warn (_("Ignoring statement due to \"%s\""), t.tit_error);    }  else    {      /* We saw no errors in any operands - try to make frag(s) */      /* Emit op-code.  */      /* Remember where it is, in case we want to modify the op-code later.  */      opcodeP = frag_more (1);      *opcodeP = t.tit_opcode;      /* Now do each operand.  */      for (operandP = t.tit_operand;	   operandP < t.tit_operand + t.tit_operands;	   operandP++)	{			/* for each operand */	  expP = &(operandP->exp_of_operand);	  if (operandP->top_ndx >= 0)	    {	      /* Indexed addressing byte	   Legality of indexed mode already checked: it is OK */	      FRAG_APPEND_1_CHAR (0x40 + operandP->top_ndx);	    }			/* if(top_ndx>=0) */	  /* Here to make main operand frag(s).  */	  this_add_number = expP->X_add_number;	  this_add_symbol = expP->X_add_symbol;	  to_seg = operandP->seg_of_operand;	  know (to_seg == SEG_UNKNOWN || \		to_seg == SEG_ABSOLUTE || \		to_seg == SEG_DATA || \		to_seg == SEG_TEXT || \		to_seg == SEG_BSS);	  is_undefined = (to_seg == SEG_UNKNOWN);	  /* Do we know how big this opperand is? */	  dispsize = operandP->top_dispsize;	  pc_rel = 0;	  /* Deal with the branch possabilities. (Note, this doesn't include	 jumps.)*/	  if (operandP->top_access == 'b')	    {	      /* Branches must be expressions. A psuedo branch can also jump to	   an absolute address.  */	      if (to_seg == now_seg || is_undefined)		{		  /* If is_undefined, then it might BECOME now_seg by relax time.  */		  if (dispsize)		    {		      /* I know how big the branch is supposed to be (it's a normal	       branch), so I set up the frag, and let GAS do the rest.  */		      p = frag_more (dispsize);		      fix_new (frag_now, p - frag_now->fr_literal,			       this_add_symbol, this_add_number,			       size_to_fx (dispsize, 1),			       NULL);		    }		  else		    {		      /* (to_seg==now_seg || to_seg == SEG_UNKNOWN) && dispsize==0 */		      /* If we don't know how big it is, then its a synthetic branch,	       so we set up a simple relax state.  */		      switch (operandP->top_width)			{			case TAHOE_WIDTH_CONDITIONAL_JUMP:			  /* Simple (conditional) jump. I may have to reverse the		 condition of opcodeP, and then jump to my destination.		 I set 1 byte aside for the branch off set, and could need 6		 more bytes for the pc_rel jump */			  frag_var (rs_machine_dependent, 7, 1,				    ENCODE_RELAX (STATE_CONDITIONAL_BRANCH,				    is_undefined ? STATE_UNDF : STATE_BYTE),				 this_add_symbol, this_add_number, opcodeP);			  break;			case TAHOE_WIDTH_ALWAYS_JUMP:			  /* Simple (unconditional) jump. I may have to convert this to		 a word branch, or an absolute jump.  */			  frag_var (rs_machine_dependent, 5, 1,				    ENCODE_RELAX (STATE_ALWAYS_BRANCH,				    is_undefined ? STATE_UNDF : STATE_BYTE),				 this_add_symbol, this_add_number, opcodeP);			  break;			  /* The smallest size for the next 2 cases is word.  */			case TAHOE_WIDTH_BIG_REV_JUMP:			  frag_var (rs_machine_dependent, 8, 2,				    ENCODE_RELAX (STATE_BIG_REV_BRANCH,				    is_undefined ? STATE_UNDF : STATE_WORD),				    this_add_symbol, this_add_number,				    opcodeP);			  break;			case TAHOE_WIDTH_BIG_NON_REV_JUMP:			  frag_var (rs_machine_dependent, 10, 2,				    ENCODE_RELAX (STATE_BIG_NON_REV_BRANCH,				    is_undefined ? STATE_UNDF : STATE_WORD),				    this_add_symbol, this_add_number,				    opcodeP);			  break;			default:			  as_fatal (_("Compliler bug: Got a case (%d) I wasn't expecting."),				    operandP->top_width);			}		    }		}	      else		{		  /* to_seg != now_seg && to_seg != seg_unknown (still in branch)	     In other words, I'm jumping out of my segment so extend the	     branches to jumps, and let GAS fix them.  */		  /* These are "branches" what will always be branches around a jump	     to the correct addresss in real life.	     If to_seg is SEG_ABSOLUTE, just encode the branch in,	     else let GAS fix the address.  */		  switch (operandP->top_width)		    {		      /* The theory:	       For SEG_ABSOLUTE, then mode is ABSOLUTE_ADDR, jump	       to that addresss (not pc_rel).	       For other segs, address is a long word PC rel jump.  */		    case TAHOE_WIDTH_CONDITIONAL_JUMP:		      /* b<cond> */		      /* To reverse the condition in a TAHOE branch,	       complement bit 4 */		      *opcodeP ^= 0x10;		      p = frag_more (7);		      *p++ = 6;		      *p++ = TAHOE_JMP;		      *p++ = (operandP->top_mode ==			      TAHOE_ABSOLUTE_ADDR ? TAHOE_ABSOLUTE_ADDR :			      TAHOE_PC_REL_LONG);		      fix_new (frag_now, p - frag_now->fr_literal,			       this_add_symbol, this_add_number,		       (to_seg != SEG_ABSOLUTE) ? FX_PCREL32 : FX_32, NULL);		      /*	     * Now (eg)	BLEQ	1f	     *		JMP	foo	     *	1:	     */		      break;		    case TAHOE_WIDTH_ALWAYS_JUMP:		      /* br, just turn it into a jump */		      *opcodeP = TAHOE_JMP;		      p = frag_more (5);		      *p++ = (operandP->top_mode ==			      TAHOE_ABSOLUTE_ADDR ? TAHOE_ABSOLUTE_ADDR :			      TAHOE_PC_REL_LONG);		      fix_new (frag_now, p - frag_now->fr_literal,			       this_add_symbol, this_add_number,		       (to_seg != SEG_ABSOLUTE) ? FX_PCREL32 : FX_32, NULL);		      /* Now (eg) JMP foo */		      break;		    case TAHOE_WIDTH_BIG_REV_JUMP:		      p = frag_more (8);		      *opcodeP ^= 0x10;		      *p++ = 0;		      *p++ = 6;		      *p++ = TAHOE_JMP;		      *p++ = (operandP->top_mode ==			      TAHOE_ABSOLUTE_ADDR ? TAHOE_ABSOLUTE_ADDR :			      TAHOE_PC_REL_LONG);		      fix_new (frag_now, p - frag_now->fr_literal,			       this_add_symbol, this_add_number,		       (to_seg != SEG_ABSOLUTE) ? FX_PCREL32 : FX_32, NULL);		      /*	     * Now (eg)	ACBx	1f	     *		JMP     foo	     *	1:	     */		      break;		    case TAHOE_WIDTH_BIG_NON_REV_JUMP:		      p = frag_more (10);		      *p++ = 0;		      *p++ = 2;		      *p++ = TAHOE_BRB;		      *p++ = 6;		      *p++ = TAHOE_JMP;		      *p++ = (operandP->top_mode ==			      TAHOE_ABSOLUTE_ADDR ? TAHOE_ABSOLUTE_ADDR :			      TAHOE_PC_REL_LONG);		      fix_new (frag_now, p - frag_now->fr_literal,			       this_add_symbol, this_add_number,		       (to_seg != SEG_ABSOLUTE) ? FX_PCREL32 : FX_32, NULL);		      /*	     * Now (eg)	xOBxxx	1f	     *		BRB	2f	     *	1:	JMP	@#foo	     *	2:	     */		      break;		    case 'b':		    case 'w':		      as_warn (_("Real branch displacements must be expressions."));		      break;		    default:		      as_fatal (_("Complier error: I got an unknown synthetic branch :%c"),				operandP->top_width);		      break;		    }		}	    }	  else	    {	      /* It ain't a branch operand.  */	      switch (operandP->top_mode)		{		  /* Auto-foo access, only works for one reg (SP)	     so the only thing needed is the mode.  */		case TAHOE_AUTO_DEC:		case TAHOE_AUTO_INC:		case TAHOE_AUTO_INC_DEFERRED:		  FRAG_APPEND_1_CHAR (operandP->top_mode);		  break;		  /* Numbered Register only access. Only thing needed is the	     mode + Register number */		case TAHOE_DIRECT_REG:		case TAHOE_REG_DEFERRED:		  FRAG_APPEND_1_CHAR (operandP->top_mode + operandP->top_reg);		  break;		  /* An absolute address. It's size is always 5 bytes.	     (mode_type + 4 byte address).  */		case TAHOE_ABSOLUTE_ADDR:		  know ((this_add_symbol == NULL));		  p = frag_more (5);		  *p = TAHOE_ABSOLUTE_ADDR;		  md_number_to_chars (p + 1, this_add_number, 4);		  break;		  /* Immediate data. If the size isn't known, then it's an address	     + and offset, which is 4 bytes big.  */		case TAHOE_IMMEDIATE:		  if (this_add_symbol != NULL)		    {		      p = frag_more (5);		      *p++ = TAHOE_IMMEDIATE_LONGWORD;		      fix_new (frag_now, p - frag_now->fr_literal,			       this_add_symbol, this_add_number,			       FX_32, NULL);		    }		  else		    {		      /* It's a integer, and I know it's size.  */		      if ((unsigned) this_add_number < 0x40)			{			  /* Will it fit in a literal? */			  FRAG_APPEND_1_CHAR ((byte) this_add_number);			}		      else			{			  p = frag_more (dispsize + 1);			  switch (dispsize)			    {			    case 1:			      *p++ = TAHOE_IMMEDIATE_BYTE;			      *p = (byte) this_add_number;			      break;			    case 2:			      *p++ = TAHOE_IMMEDIATE_WORD;			      md_number_to_chars (p, this_add_number, 2);			      break;			    case 4:			      *p++ = TAHOE_IMMEDIATE_LONGWORD;			      md_number_to_chars (p, this_add_number, 4);			      break;			    }			}		    }		  break;		  /* Distance from the PC. If the size isn't known, we have to relax	     into it. The difference between this and disp(sp) is that	     this offset is pc_rel, and disp(sp) isn't.	     Note the drop through code.  */		case TAHOE_DISPLACED_RELATIVE:		case TAHOE_DISP_REL_DEFERRED:		  operandP->top_reg = PC_REG;		  pc_rel = 1;		  /* Register, plus a displacement mode. Save the register number,	     and weather its deffered or not, and relax the size if it isn't	     known.  */		case TAHOE_REG_DISP:		case TAHOE_REG_DISP_DEFERRED:		  if (operandP->top_mode == TAHOE_DISP_REL_DEFERRED ||		      operandP->top_mode == TAHOE_REG_DISP_DEFERRED)		    operandP->top_reg += 0x10;	/* deffered mode is always 0x10 higher					  than it's non-deffered sibling.  */		  /* Is this a value out of this segment?	     The first part of this conditional is a cludge to make gas	     produce the same output as 'as' when there is a lable, in	     the current segment, displaceing a register. It's strange,	     and no one in their right mind would do it, but it's easy	     to cludge.  */		  if ((dispsize == 0 && !pc_rel) ||		      (to_seg != now_seg && !is_undefined && to_seg != SEG_ABSOLUTE))		    dispsize = 4;		  if (dispsize == 0)		    {		      /*	     * We have a SEG_UNKNOWN symbol, or the size isn't cast.	     * It might turn out to be in the same segment as	     * the instruction, permitting relaxation.	     */		      p = frag_var (rs_machine_dependent, 5, 2,				    ENCODE_RELAX (STATE_PC_RELATIVE,				    is_undefined ? STATE_UNDF : STATE_BYTE),				    this_add_symbol, this_add_number, 0);		      *p = operandP->top_reg;		    }		  else		    {		      /* Either this is an abs, or a cast.  */		      p = frag_more (dispsize + 1);		      switch (dispsize)			{			case 1:			  *p = TAHOE_PC_OR_BYTE + operandP->top_reg;			  break;			case 2:			  *p = TAHOE_PC_OR_WORD + operandP->top_reg;			  break;			case 4:			  *p = TAHOE_PC_OR_LONG + operandP->top_reg;			  break;			};		      fix_new (frag_now, p + 1 - frag_now->fr_literal,			       this_add_symbol, this_add_number,			       size_to_fx (dispsize, pc_rel), NULL);		    }		  break;		default:		  as_fatal (_("Barf, bad mode %x\n"), operandP->top_mode);		}	    }	}			/* for(operandP) */    }				/* if(!need_pass_2 && !goofed) */}				/* tahoe_assemble() *//* We have no need to default values of symbols.  */symbolS *md_undefined_symbol (name)     char *name;{  return 0;}				/* md_undefined_symbol() *//* Round up a section size to the appropriate boundary.  */valueTmd_section_align (segment, size)     segT segment;     valueT size;{  return ((size + 7) & ~7);	/* Round all sects to multiple of 8 */}				/* md_section_align() *//* Exactly what point is a PC-relative offset relative TO?   On the sparc, they're relative to the address of the offset, plus   its size.  This gets us to the following instruction.   (??? Is this right?  FIXME-SOON) */longmd_pcrel_from (fixP)     fixS *fixP;{  return (((fixP->fx_type == FX_8	    || fixP->fx_type == FX_PCREL8)	   ? 1	   : ((fixP->fx_type == FX_16	       || fixP->fx_type == FX_PCREL16)	      ? 2	      : ((fixP->fx_type == FX_32		  || fixP->fx_type == FX_PCREL32)		 ? 4		 : 0))) + fixP->fx_where + fixP->fx_frag->fr_address);}				/* md_pcrel_from() */inttc_is_pcrel (fixP)     fixS *fixP;{  /* should never be called */  know (0);  return (0);}				/* tc_is_pcrel() */

⌨️ 快捷键说明

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