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

📄 vax.c

📁 早期freebsd实现
💻 C
📖 第 1 页 / 共 5 页
字号:
  int length;			/* length (bytes) meant by vop_short. */  int at;			/* 0, or 1 if '@' is in addressing mode. */  int nbytes;			/* From vop_nbytes: vax_operand_width (in bytes) */  FLONUM_TYPE *floatP;  char *vip ();  LITTLENUM_TYPE literal_float[8];  /* Big enough for any floating point literal. */  if (*(p = vip (&v, instruction_string)))    {      as_fatal ("vax_assemble\"%s\" in=\"%s\"", p, instruction_string);    }  /*   * Now we try to find as many as_warn()s as we can. If we do any as_warn()s   * then goofed=TRUE. Notice that we don't make any frags yet.   * Should goofed be TRUE, 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 (goofed = (*v.vit_error))    {      as_warn ("Ignoring statement due to \"%s\"", v.vit_error);    }  /*   * We need to use expression() and friends, which require us to diddle   * input_line_pointer. So we save it and restore it later.   */  save_input_line_pointer = input_line_pointer;  for (operandP = v.vit_operand,       expP = exp_of_operand,       floatP = float_operand,       end_operandP = v.vit_operand + v.vit_operands;       operandP < end_operandP;       operandP++,       expP++,       floatP++    )				/* for each operand */    {      if (*(operandP->vop_error))	{	  as_warn ("Ignoring statement because \"%s\"", (operandP->vop_error));	  goofed = TRUE;	}      else	{			/* statement has no syntax goofs: lets sniff the expression */	  int can_be_short;	/* TRUE if a bignum can be reduced to a short literal. */	  input_line_pointer = operandP->vop_expr_begin;	  c_save = operandP->vop_expr_end[1];	  operandP->vop_expr_end[1] = '\0';	  /* If to_seg == SEG_PASS1, expression() will have set need_pass_2 = TRUE. */	  switch (to_seg = expression (expP))	    {	    case SEG_NONE:	      /* for BSD4.2 compatibility, missing expression is absolute 0 */	      to_seg = expP->X_seg = SEG_ABSOLUTE;	      expP->X_add_number = 0;	      /* for SEG_ABSOLUTE, we shouldnt need to set X_subtract_symbol, X_add_symbol to any particular value. */	      /* But, we will program defensively. Since this situation occurs */	      /* rarely so it costs us little to do, and stops Dean */	      /* worrying about the origin of random bits in expressionS's. */	      expP->X_add_symbol = NULL;	      expP->X_subtract_symbol = NULL;	    case SEG_TEXT:	    case SEG_DATA:	    case SEG_BSS:	    case SEG_ABSOLUTE:	    case SEG_UNKNOWN:	      break;	    case SEG_DIFFERENCE:	    case SEG_PASS1:	      /*	       * Major bug. We can't handle the case of a	       * SEG_DIFFERENCE expression in a VIT_OPCODE_SYNTHETIC	       * variable-length instruction.	       * We don't have a frag type that is smart enough to	       * relax a SEG_DIFFERENCE, and so we just force all	       * SEG_DIFFERENCEs to behave like SEG_PASS1s.	       * Clearly, if there is a demand we can invent a new or	       * modified frag type and then coding up a frag for this	       * case will be easy. SEG_DIFFERENCE was invented for the	       * .words after a CASE opcode, and was never intended for	       * instruction operands.	       */	      need_pass_2 = TRUE;	      as_warn("Can't relocate expression");	      break;	    case SEG_BIG:	      /* Preserve the bits. */	      if (expP->X_add_number > 0)		{		  bignum_copy (generic_bignum, expP->X_add_number,			       floatP->low, SIZE_OF_LARGE_NUMBER);		}	      else		{		  know (expP->X_add_number < 0);		  flonum_copy (&generic_floating_point_number,			       floatP);		  if (index ("s i", operandP->vop_short))		    {		/* Could possibly become S^# */		      flonum_gen2vax (-expP->X_add_number, floatP, literal_float);		      switch (-expP->X_add_number)			{			case 'f':			  can_be_short =			    (literal_float[0] & 0xFC0F) == 0x4000			    && literal_float[1] == 0;			  break;			case 'd':			  can_be_short =			    (literal_float[0] & 0xFC0F) == 0x4000			    && literal_float[1] == 0			    && literal_float[2] == 0			    && literal_float[3] == 0;			  break;			case 'g':			  can_be_short =			    (literal_float[0] & 0xFF81) == 0x4000			    && literal_float[1] == 0			    && literal_float[2] == 0			    && literal_float[3] == 0;			  break;			case 'h':			  can_be_short =			    (literal_float[0] & 0xFFF8) == 0x4000			    && (literal_float[1] & 0xE000) == 0			    && literal_float[2] == 0			    && literal_float[3] == 0			    && literal_float[4] == 0			    && literal_float[5] == 0			    && literal_float[6] == 0			    && literal_float[7] == 0;			  break;			default:			  BAD_CASE (-expP->X_add_number);			  break;			}	/* switch (float type) */		    }		/* if (could want to become S^#...) */		}		/* bignum or flonum ? */	      if (operandP->vop_short == 's'		  || operandP->vop_short == 'i'		  || (operandP->vop_short == ' '		      && operandP->vop_reg == 0xF		      && (operandP->vop_mode & 0xE) == 0x8))		{		  /* Saw a '#'. */		  if (operandP->vop_short == ' ')		    {		/* We must chose S^ or I^. */		      if (expP->X_add_number > 0)			{	/* Bignum: Short literal impossible. */			  operandP->vop_short = 'i';			  operandP->vop_mode = 8;			  operandP->vop_reg = 0xF;	/* VAX PC. */			}		      else			{	/* Flonum: Try to do it. */			  if (can_be_short)			    {			      operandP->vop_short = 's';			      operandP->vop_mode = 0;			      operandP->vop_ndx = -1;			      operandP->vop_reg = -1;			      /* JF hope this is the right thing */			      expP->X_seg = SEG_ABSOLUTE;			    }			  else			    {			      operandP->vop_short = 'i';			      operandP->vop_mode = 8;			      operandP->vop_reg = 0xF;	/* VAX PC */			    }			}	/* bignum or flonum ? */		    }		/*  if #, but no S^ or I^ seen. */		  /* No more ' ' case: either 's' or 'i'. */		  if (operandP->vop_short == 's')		    {		      /* Wants to be a short literal. */		      if (expP->X_add_number > 0)			{			  as_warn ("Bignum not permitted in short literal. Immediate mode assumed.");			  operandP->vop_short = 'i';			  operandP->vop_mode = 8;			  operandP->vop_reg = 0xF;	/* VAX PC. */			}		      else			{			  if (!can_be_short)			    {			      as_warn ("Can't do flonum short literal: immediate mode used.");			      operandP->vop_short = 'i';			      operandP->vop_mode = 8;			      operandP->vop_reg = 0xF;	/* VAX PC. */			    }			  else			    {	/* Encode short literal now. */			      register int temp;			      switch (-expP->X_add_number)				{				case 'f':				case 'd':				  temp = literal_float[0] >> 4;				  break;				case 'g':				  temp = literal_float[0] >> 1;				  break;				case 'h':				  temp = ((literal_float[0] << 3) & 070)				    | ((literal_float[1] >> 13) & 07);				  break;				default:				  BAD_CASE (-expP->X_add_number);				  break;				}			      floatP->low[0] = temp & 077;			      floatP->low[1] = 0;			    }	/* if can be short literal float */			}	/* flonum or bignum ? */		    }		  else		    {		/* I^# seen: set it up if float. */		      if (expP->X_add_number < 0)			{			  bcopy (literal_float, floatP->low, sizeof (literal_float));			}		    }		/* if S^# seen. */		}	      else		{		  as_warn ("A bignum/flonum may not be a displacement: 0x%x used",			   expP->X_add_number = 0x80000000);		  /* Chosen so luser gets the most offset bits to patch later. */		}	      expP->X_add_number = floatP->low[0]		| ((LITTLENUM_MASK & (floatP->low[1])) << LITTLENUM_NUMBER_OF_BITS);/* * For the SEG_BIG case we have: * If vop_short == 's' then a short floating literal is in the *	lowest 6 bits of floatP -> low [0], which is *	big_operand_bits [---] [0]. * If vop_short == 'i' then the appropriate number of elements *	of big_operand_bits [---] [...] are set up with the correct *	bits. * Also, just in case width is byte word or long, we copy the lowest * 32 bits of the number to X_add_number. */	      break;	    default:	      BAD_CASE (to_seg);	      break;	    }	  if (input_line_pointer != operandP->vop_expr_end + 1)	    {	      as_warn ("Junk at end of expression \"%s\"", input_line_pointer);	      goofed = TRUE;	    }	  operandP->vop_expr_end[1] = c_save;	}    }				/* for(each operand) */  input_line_pointer = save_input_line_pointer;  if (!need_pass_2 && !goofed)    {      /* We saw no errors in any operands - try to make frag(s) */      int is_undefined;		/* True if operand expression's */      /* segment not known yet. */      int length_code;      /* Emit op-code. */      /* Remember where it is, in case we want to modify the op-code later. */      opcode_low_byteP = frag_more (v.vit_opcode_nbytes);      bcopy (v.vit_opcode, opcode_low_byteP, v.vit_opcode_nbytes);      opcode_as_number = md_chars_to_number (opcode_as_chars = v.vit_opcode, 4);      for (operandP = v.vit_operand,	   expP = exp_of_operand,	   floatP = float_operand,	   end_operandP = v.vit_operand + v.vit_operands;	   operandP < end_operandP;	   operandP++,	   floatP++,	   expP++	)			/* for each operand */	{	  if (operandP->vop_ndx >= 0)	    {	      /* indexed addressing byte */	      /* Legality of indexed mode already checked: it is OK */	      FRAG_APPEND_1_CHAR (0x40 + operandP->vop_ndx);	    }			/* if(vop_ndx>=0) */	  /* Here to make main operand frag(s). */	  this_add_number = expP->X_add_number;	  this_add_symbol = expP->X_add_symbol;	  this_subtract_symbol = expP->X_subtract_symbol;	  to_seg = expP->X_seg;	  is_undefined = (to_seg == SEG_UNKNOWN);	  know (to_seg == SEG_UNKNOWN \		||to_seg == SEG_ABSOLUTE \		||to_seg == SEG_DATA \		||to_seg == SEG_TEXT \		||to_seg == SEG_BSS \		||to_seg == SEG_BIG \	    );	  at = operandP->vop_mode & 1;	  length = operandP->vop_short == 'b' ? 1 : operandP->vop_short == 'w' ? 2 : operandP->vop_short == 'l' ? 4 : 0;	  nbytes = operandP->vop_nbytes;	  if (operandP->vop_access == 'b')	    {	      if (to_seg == now_seg || is_undefined)		{		/* If is_undefined, then it might BECOME now_seg. */		  if (nbytes)		    {		      p = frag_more (nbytes);		      fix_new (frag_now, p - frag_now->fr_literal, nbytes,			       this_add_symbol, 0, this_add_number, 1);		    }		  else		    {		/* to_seg==now_seg || to_seg == SEG_UNKNOWN */		      /* nbytes==0 */		      length_code = is_undefined ? STATE_UNDF : STATE_BYTE;		      if (opcode_as_number & VIT_OPCODE_SPECIAL)			{			  if (operandP->vop_width == VAX_WIDTH_UNCONDITIONAL_JUMP)			    {			      /* br or jsb */			      frag_var (rs_machine_dependent, 5, 1,					ENCODE_RELAX (STATE_ALWAYS_BRANCH, length_code),					this_add_symbol, this_add_number,					opcode_low_byteP);			    }			  else			    {			      if (operandP->vop_width == VAX_WIDTH_WORD_JUMP)				{				  length_code = STATE_WORD;	/* JF: There is no state_byte for this one! */				  frag_var (rs_machine_dependent, 10, 2,					    ENCODE_RELAX (STATE_COMPLEX_BRANCH, length_code),					    this_add_symbol, this_add_number,					    opcode_low_byteP);				}			      else				{				  know (operandP->vop_width == VAX_WIDTH_BYTE_JUMP);				  frag_var (rs_machine_dependent, 9, 1,					    ENCODE_RELAX (STATE_COMPLEX_HOP, length_code),					    this_add_symbol, this_add_number,					    opcode_low_byteP);				}			    }			}		      else			{			  know (operandP->vop_width == VAX_WIDTH_CONDITIONAL_JUMP);			  frag_var (rs_machine_dependent, 7, 1,				    ENCODE_RELAX (STATE_CONDITIONAL_BRANCH, length_code),				    this_add_symbol, this_add_number,				    opcode_low_byteP);			}		    }		}	      else		{		/* to_seg != now_seg && to_seg != SEG_UNKNOWN *//* * --- SEG FLOAT MAY APPEAR HERE ---- */		  if (to_seg == SEG_ABSOLUTE)		    {		      if (nbytes)			{			  know (!(opcode_as_number & VIT_OPCODE_SYNTHETIC));			  p = frag_more (nbytes);			  /* Conventional relocation. */			  fix_new (frag_now, p - frag_now->fr_literal,				nbytes, &abs_symbol, 0, this_add_number, 1);			}		      else			{			  know (opcode_as_number & VIT_OPCODE_SYNTHETIC);			  if (opcode_as_number & VIT_OPCODE_SPECIAL)			    {			      if (operandP->vop_width == VAX_WIDTH_UNCONDITIONAL_JUMP)				{				  /* br or jsb */				  *opcode_low_byteP = opcode_as_chars[0] + VAX_WIDEN_LONG;				  know (opcode_as_chars[1] == 0);				  p = frag_more (5);				  p[0] = VAX_ABSOLUTE_MODE;	/* @#... */				  md_number_to_chars (p + 1, this_add_number, 4);				  /* Now (eg) JMP @#foo or JSB @#foo. */				}			      else				{				  if (operandP->vop_width == VAX_WIDTH_WORD_JUMP)				    {				      p = frag_more (10);				      p[0] = 2;				      p[1] = 0;				      p[2] = VAX_BRB;				      p[3] = 6;				      p[4] = VAX_JMP;				      p[5] = VAX_ABSOLUTE_MODE;	/* @#... */				      md_number_to_chars (p + 6, this_add_number, 4);				      /*				       * Now (eg)	ACBx	1f				       *		BRB	2f				       *	1:	JMP	@#foo				       *	2:				       */				    }				  else				    {				      know (operandP->vop_width == VAX_WIDTH_BYTE_JUMP);				      p = frag_more (9);				      p[0] = 2;				      p[1] = VAX_BRB;				      p[2] = 6;				      p[3] = VAX_JMP;				      p[4] = VAX_PC_RELATIVE_MODE + 1;	/* @#... */				      md_number_to_chars (p + 5, this_add_number, 4);				      /*				       * Now (eg)	xOBxxx	1f				       *		BRB	2f				       *	1:	JMP	@#foo				       *	2:				       */				    }				}			    }

⌨️ 快捷键说明

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