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

📄 i386.c

📁 早期freebsd实现
💻 C
📖 第 1 页 / 共 4 页
字号:
	switch (num) {	/* must be 1 digit scale */	case 1: i.log2_scale_factor = 0; break;	case 2: i.log2_scale_factor = 1; break;	case 4: i.log2_scale_factor = 2; break;	case 8: i.log2_scale_factor = 3; break;	default:	  as_bad ("expecting scale factor of 1, 2, 4, 8; got %d", num);	  return 0;	}      } else {	if (! i.index_reg && *base_string == ',') {	  as_bad ("expecting index register or scale factor after ','; got '%c'",		   *(base_string+1));	  return 0;	}      }    }    /* If there's an expression begining the operand, parse it,       assuming displacement_string_start and displacement_string_end       are meaningful. */    if (displacement_string_start) {      register expressionS * exp;      segT exp_seg;      char * save_input_line_pointer;      exp = &disp_expressions[i.disp_operands];      i.disps [this_operand] = exp;      i.disp_operands++;      save_input_line_pointer = input_line_pointer;      input_line_pointer = displacement_string_start;      END_STRING_AND_SAVE (displacement_string_end);      exp_seg = expression (exp);      if(*input_line_pointer)	as_bad("Ignoring junk '%s' after expression",input_line_pointer);      RESTORE_END_STRING (displacement_string_end);      input_line_pointer = save_input_line_pointer;      switch (exp_seg) {      case SEG_NONE:	/* missing expr becomes absolute 0 */	as_bad ("missing or invalid displacement '%s' taken as 0",		 operand_string);	i.types[this_operand] |= (Disp|Abs);	exp->X_seg = SEG_ABSOLUTE;	exp->X_add_number = 0;	exp->X_add_symbol = (symbolS *) 0;	exp->X_subtract_symbol = (symbolS *) 0;	break;      case SEG_ABSOLUTE:	i.types[this_operand] |= SMALLEST_DISP_TYPE (exp->X_add_number);	break;      case SEG_TEXT: case SEG_DATA: case SEG_BSS:      case SEG_UNKNOWN:	/* must be 32 bit displacement (i.e. address) */	i.types[this_operand] |= Disp32;	break;      default:	goto seg_unimplemented;      }    }    /* Make sure the memory operand we've been dealt is valid. */    if (i.base_reg && i.index_reg &&	! (i.base_reg->reg_type & i.index_reg->reg_type & Reg)) {      as_bad ("register size mismatch in (base,index,scale) expression");      return 0;    }    if ((i.base_reg && (i.base_reg->reg_type & Reg32) == 0) ||	(i.index_reg && (i.index_reg->reg_type & Reg32) == 0)) {      as_bad ("base/index register must be 32 bit register");      return 0;    }    if (i.index_reg && i.index_reg == esp) {      as_bad ("%s may not be used as an index register", esp->reg_name);      return 0;    }  } else {			/* it's not a memory operand; argh! */    as_bad ("invalid char %s begining %s operand '%s'",	     output_invalid(*op_string), ordinal_names[this_operand],	     op_string);    return 0;  }  return 1;			/* normal return */}/* *			md_estimate_size_before_relax() * * Called just before relax(). * Any symbol that is now undefined will not become defined. * Return the correct fr_subtype in the frag. * Return the initial "guess for fr_var" to caller. * The guess for fr_var is ACTUALLY the growth beyond fr_fix. * Whatever we do to grow fr_fix or fr_var contributes to our returned value. * Although it may not be explicit in the frag, pretend fr_var starts with a * 0 value. */intmd_estimate_size_before_relax (fragP, segment_type)     register fragS *	fragP;     register int	segment_type; /* N_DATA or N_TEXT. */{  register uchar *	opcode;  register int		old_fr_fix;  old_fr_fix = fragP -> fr_fix;  opcode = (uchar *) fragP -> fr_opcode;  /* We've already got fragP->fr_subtype right;  all we have to do is check     for un-relaxable symbols. */  if ((fragP -> fr_symbol -> sy_type & N_TYPE) != segment_type) {    /* symbol is undefined in this segment */    switch (opcode[0]) {    case JUMP_PC_RELATIVE:	/* make jmp (0xeb) a dword displacement jump */      opcode[0] = 0xe9;		/* dword disp jmp */      fragP -> fr_fix += 4;      fix_new (fragP, old_fr_fix, 4,	       fragP -> fr_symbol,	       (symbolS *) 0,	       fragP -> fr_offset, 1);      break;    default:      /* This changes the byte-displacement jump 0x7N -->	 the dword-displacement jump 0x0f8N */      opcode[1] = opcode[0] + 0x10;      opcode[0] = TWO_BYTE_OPCODE_ESCAPE;		/* two-byte escape */      fragP -> fr_fix += 1 + 4;	/* we've added an opcode byte */      fix_new (fragP, old_fr_fix + 1, 4,	       fragP -> fr_symbol,	       (symbolS *) 0,	       fragP -> fr_offset, 1);      break;    }    frag_wane (fragP);  }  return (fragP -> fr_var + fragP -> fr_fix - old_fr_fix);}				/* md_estimate_size_before_relax() *//* *			md_convert_frag(); * * Called after relax() is finished. * In:	Address of frag. *	fr_type == rs_machine_dependent. *	fr_subtype is what the address relaxed to. * * Out:	Any fixSs and constants are set up. *	Caller will turn frag into a ".space 0". */voidmd_convert_frag (fragP)     register fragS *	fragP;{  register uchar * opcode;  uchar * where_to_put_displacement;  uint target_address, opcode_address;  uint extension;  int displacement_from_opcode_start;  opcode = (uchar *) fragP -> fr_opcode;  /* Address we want to reach in file space. */  target_address = fragP->fr_symbol->sy_value + fragP->fr_offset;  /* Address opcode resides at in file space. */  opcode_address = fragP->fr_address + fragP->fr_fix;  /* Displacement from opcode start to fill into instruction. */  displacement_from_opcode_start = target_address - opcode_address;  switch (fragP->fr_subtype) {  case ENCODE_RELAX_STATE (COND_JUMP, BYTE):  case ENCODE_RELAX_STATE (UNCOND_JUMP, BYTE):    /* don't have to change opcode */    extension = 1;		/* 1 opcode + 1 displacement */    where_to_put_displacement = &opcode[1];    break;  case ENCODE_RELAX_STATE (COND_JUMP, WORD):    opcode[1] = TWO_BYTE_OPCODE_ESCAPE;    opcode[2] = opcode[0] + 0x10;    opcode[0] = WORD_PREFIX_OPCODE;    extension = 4;		/* 3 opcode + 2 displacement */    where_to_put_displacement = &opcode[3];    break;  case ENCODE_RELAX_STATE (UNCOND_JUMP, WORD):    opcode[1] = 0xe9;    opcode[0] = WORD_PREFIX_OPCODE;    extension = 3;		/* 2 opcode + 2 displacement */    where_to_put_displacement = &opcode[2];    break;  case ENCODE_RELAX_STATE (COND_JUMP, DWORD):    opcode[1] = opcode[0] + 0x10;    opcode[0] = TWO_BYTE_OPCODE_ESCAPE;    extension = 5;		/* 2 opcode + 4 displacement */    where_to_put_displacement = &opcode[2];    break;  case ENCODE_RELAX_STATE (UNCOND_JUMP, DWORD):    opcode[0] = 0xe9;    extension = 4;		/* 1 opcode + 4 displacement */    where_to_put_displacement = &opcode[1];    break;  default:    BAD_CASE(fragP -> fr_subtype);    break;  }  /* now put displacement after opcode */  md_number_to_chars (where_to_put_displacement,		      displacement_from_opcode_start - extension,		      SIZE_FROM_RELAX_STATE (fragP->fr_subtype));  fragP -> fr_fix += extension;}int md_short_jump_size = 2;	/* size of byte displacement jmp */int md_long_jump_size  = 5;	/* size of dword displacement jmp */void md_create_short_jump(ptr, from_addr, to_addr)     char	*ptr;     long	from_addr, to_addr;{  long offset;  offset = to_addr - (from_addr + 2);  md_number_to_chars (ptr, (long) 0xeb, 1); /* opcode for byte-disp jump */  md_number_to_chars (ptr + 1, offset, 1);}void md_create_long_jump (ptr, from_addr, to_addr, frag, to_symbol)     char	*ptr;     long	from_addr, to_addr;     fragS	*frag;     symbolS	*to_symbol;{  long offset;  if (flagseen['m']) {    offset = to_addr - to_symbol->sy_value;    md_number_to_chars (ptr, 0xe9, 1); /* opcode for long jmp */    md_number_to_chars (ptr + 1, offset, 4);    fix_new (frag, (ptr+1) - frag->fr_literal, 4,	     to_symbol, (symbolS *) 0, (long int) 0, 0);  } else {    offset = to_addr - (from_addr + 5);    md_number_to_chars(ptr, (long) 0xe9, 1);    md_number_to_chars(ptr + 1, offset, 4);  }}intmd_parse_option(argP,cntP,vecP)char **argP;int *cntP;char ***vecP;{	return 1;}void				/* Knows about order of bytes in address. */md_number_to_chars (con, value, nbytes)     char	con [];	/* Return 'nbytes' of chars here. */     long int	value;		/* The value of the bits. */     int	nbytes;		/* Number of bytes in the output. */{  register char * p = con;  switch (nbytes) {  case 1:    p[0] = value & 0xff;    break;  case 2:    p[0] = value & 0xff;    p[1] = (value >> 8) & 0xff;    break;  case 4:    p[0] = value & 0xff;    p[1] = (value>>8) & 0xff;    p[2] = (value>>16) & 0xff;    p[3] = (value>>24) & 0xff;    break;  default:    BAD_CASE (nbytes);  }}void				/* Knows about order of bytes in address. */md_number_to_disp (con, value, nbytes)     char	con [];	/* Return 'nbytes' of chars here. */     long int	value;		/* The value of the bits. */     int	nbytes;		/* Number of bytes in the output. */{  char * answer = alloca (nbytes);  register char * p = answer;  switch (nbytes) {  case 1:    *p = value;    break;  case 2:    *p++   = value;    *p = (value>>8);    break;  case 4:    *p++ = value;    *p++ = (value>>8);    *p++ = (value>>16);    *p = (value>>24);    break;  default:    BAD_CASE (nbytes);  }  bcopy (answer, con, nbytes);}void				/* Knows about order of bytes in address. */md_number_to_imm (con, value, nbytes)     char	con [];	/* Return 'nbytes' of chars here. */     long int	value;		/* The value of the bits. */     int	nbytes;		/* Number of bytes in the output. */{  char * answer = alloca (nbytes);  register char * p = answer;  switch (nbytes) {  case 1:    *p = value;    break;  case 2:    *p++   = value;    *p = (value>>8);    break;  case 4:    *p++ = value;    *p++ = (value>>8);    *p++ = (value>>16);    *p = (value>>24);    break;  default:    BAD_CASE (nbytes);  }  bcopy (answer, con, nbytes);}void				/* Knows about order of bytes in address. */md_number_to_field (con, value, nbytes)     char	con [];	/* Return 'nbytes' of chars here. */     long int	value;		/* The value of the bits. */     int	nbytes;		/* Number of bytes in the output. */{  char * answer = alloca (nbytes);  register char * p = answer;  switch (nbytes) {  case 1:    *p = value;    break;  case 2:    *p++   = value;    *p = (value>>8);    break;  case 4:    *p++ = value;    *p++ = (value>>8);    *p++ = (value>>16);    *p = (value>>24);    break;  default:    BAD_CASE (nbytes);  }  bcopy (answer, con, nbytes);}long int			/* Knows about the byte order in a word. */md_chars_to_number (con, nbytes)unsigned     char	con[];	/* Low order byte 1st. */     int	nbytes;		/* Number of bytes in the input. */{  long int	retval;  for (retval=0, con+=nbytes-1; nbytes--; con--)    {      retval <<= BITS_PER_CHAR;      retval |= *con;    }  return retval;}void md_ri_to_chars(ri_p, ri)     struct relocation_info *ri_p, ri;{  unsigned char the_bytes[8];    /* this is easy */  md_number_to_chars(the_bytes, ri.r_address, sizeof(ri.r_address));  /* now the fun stuff */  the_bytes[6] = (ri.r_symbolnum >> 16) & 0x0ff;  the_bytes[5] = (ri.r_symbolnum >> 8) & 0x0ff;  the_bytes[4] = ri.r_symbolnum & 0x0ff;  the_bytes[7] = (((ri.r_extern << 3)  & 0x08) | ((ri.r_length << 1) & 0x06) |     ((ri.r_pcrel << 0)  & 0x01)) & 0x0F;   /* now put it back where you found it */  bcopy (the_bytes, (char *)ri_p, sizeof(struct relocation_info));}#define MAX_LITTLENUMS 6/* Turn the string pointed to by litP into a floating point constant of type   type, and emit the appropriate bytes.  The number of LITTLENUMS emitted   is stored in *sizeP .  An error message is returned, or NULL on OK. */char *md_atof(type,litP,sizeP)     char type;     char *litP;     int *sizeP;{  int	prec;  LITTLENUM_TYPE words[MAX_LITTLENUMS];  LITTLENUM_TYPE *wordP;  char	*t;  char	*atof_ieee();  switch(type) {  case 'f':  case 'F':    prec = 2;    break;  case 'd':  case 'D':    prec = 4;    break;  case 'x':  case 'X':    prec = 5;    break;  default:    *sizeP=0;    return "Bad call to md_atof ()";  }  t = atof_ieee (input_line_pointer,type,words);  if(t)    input_line_pointer=t;  *sizeP = prec * sizeof(LITTLENUM_TYPE);  /* this loops outputs the LITTLENUMs in REVERSE order; in accord with     the bigendian 386 */  for(wordP = words + prec - 1;prec--;) {    md_number_to_chars (litP, (long) (*wordP--), sizeof(LITTLENUM_TYPE));    litP += sizeof(LITTLENUM_TYPE);  }  return "";	/* Someone should teach Dean about null pointers */}char output_invalid_buf[8];char * output_invalid (c)     char c;{  if (isprint(c)) sprintf (output_invalid_buf, "'%c'", c);  else sprintf (output_invalid_buf, "(0x%x)", c);  return output_invalid_buf;}reg_entry *parse_register (reg_string)    char *reg_string;          /* reg_string starts *before* REGISTER_PREFIX */{  register char *s = reg_string;  register char *p;  char reg_name_given[MAX_REG_NAME_SIZE];  s++;				/* skip REGISTER_PREFIX */  for (p = reg_name_given; is_register_char (*s); p++, s++) {    *p = register_chars [*s];    if (p >= reg_name_given + MAX_REG_NAME_SIZE)      return (reg_entry *) 0;  }  *p = '\0';  return (reg_entry *) hash_find (reg_hash, reg_name_given);}

⌨️ 快捷键说明

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