tc-i386.c

来自「基于4个mips核的noc设计」· C语言 代码 · 共 2,311 行 · 第 1/5 页

C
2,311
字号
      else	memcpy (fragP->fr_literal + fragP->fr_fix,		f32_patt[count - 1], count);      fragP->fr_var = count;    }}static char *output_invalid PARAMS ((int c));static int i386_operand PARAMS ((char *operand_string));static int i386_intel_operand PARAMS ((char *operand_string, int got_a_float));static const reg_entry *parse_register PARAMS ((char *reg_string,						char **end_op));#ifndef I386COFFstatic void s_bss PARAMS ((int));#endifsymbolS *GOT_symbol;		/* Pre-defined "_GLOBAL_OFFSET_TABLE_".  */static INLINE unsigned intmode_from_disp_size (t)     unsigned int t;{  return (t & Disp8) ? 1 : (t & (Disp16 | Disp32 | Disp32S)) ? 2 : 0;}static INLINE intfits_in_signed_byte (num)     offsetT num;{  return (num >= -128) && (num <= 127);}static INLINE intfits_in_unsigned_byte (num)     offsetT num;{  return (num & 0xff) == num;}static INLINE intfits_in_unsigned_word (num)     offsetT num;{  return (num & 0xffff) == num;}static INLINE intfits_in_signed_word (num)     offsetT num;{  return (-32768 <= num) && (num <= 32767);}static INLINE intfits_in_signed_long (num)     offsetT num ATTRIBUTE_UNUSED;{#ifndef BFD64  return 1;#else  return (!(((offsetT) -1 << 31) & num)	  || (((offsetT) -1 << 31) & num) == ((offsetT) -1 << 31));#endif}				/* fits_in_signed_long() */static INLINE intfits_in_unsigned_long (num)     offsetT num ATTRIBUTE_UNUSED;{#ifndef BFD64  return 1;#else  return (num & (((offsetT) 2 << 31) - 1)) == num;#endif}				/* fits_in_unsigned_long() */static intsmallest_imm_type (num)     offsetT num;{  if (cpu_arch_flags != (Cpu086 | Cpu186 | Cpu286 | Cpu386 | Cpu486 | CpuNo64)      && !(cpu_arch_flags & (CpuUnknown)))    {      /* This code is disabled on the 486 because all the Imm1 forms	 in the opcode table are slower on the i486.  They're the	 versions with the implicitly specified single-position	 displacement, which has another syntax if you really want to	 use that form.  */      if (num == 1)	return Imm1 | Imm8 | Imm8S | Imm16 | Imm32 | Imm32S | Imm64;    }  return (fits_in_signed_byte (num)	  ? (Imm8S | Imm8 | Imm16 | Imm32 | Imm32S | Imm64)	  : fits_in_unsigned_byte (num)	  ? (Imm8 | Imm16 | Imm32 | Imm32S | Imm64)	  : (fits_in_signed_word (num) || fits_in_unsigned_word (num))	  ? (Imm16 | Imm32 | Imm32S | Imm64)	  : fits_in_signed_long (num)	  ? (Imm32 | Imm32S | Imm64)	  : fits_in_unsigned_long (num)	  ? (Imm32 | Imm64)	  : Imm64);}static offsetToffset_in_range (val, size)     offsetT val;     int size;{  addressT mask;  switch (size)    {    case 1: mask = ((addressT) 1 <<  8) - 1; break;    case 2: mask = ((addressT) 1 << 16) - 1; break;    case 4: mask = ((addressT) 2 << 31) - 1; break;#ifdef BFD64    case 8: mask = ((addressT) 2 << 63) - 1; break;#endif    default: abort ();    }  /* If BFD64, sign extend val.  */  if (!use_rela_relocations)    if ((val & ~(((addressT) 2 << 31) - 1)) == 0)      val = (val ^ ((addressT) 1 << 31)) - ((addressT) 1 << 31);  if ((val & ~mask) != 0 && (val & ~mask) != ~mask)    {      char buf1[40], buf2[40];      sprint_value (buf1, val);      sprint_value (buf2, val & mask);      as_warn (_("%s shortened to %s"), buf1, buf2);    }  return val & mask;}/* Returns 0 if attempting to add a prefix where one from the same   class already exists, 1 if non rep/repne added, 2 if rep/repne   added.  */static intadd_prefix (prefix)     unsigned int prefix;{  int ret = 1;  int q;  if (prefix >= 0x40 && prefix < 0x50 && flag_code == CODE_64BIT)    q = REX_PREFIX;  else    switch (prefix)      {      default:	abort ();      case CS_PREFIX_OPCODE:      case DS_PREFIX_OPCODE:      case ES_PREFIX_OPCODE:      case FS_PREFIX_OPCODE:      case GS_PREFIX_OPCODE:      case SS_PREFIX_OPCODE:	q = SEG_PREFIX;	break;      case REPNE_PREFIX_OPCODE:      case REPE_PREFIX_OPCODE:	ret = 2;	/* fall thru */      case LOCK_PREFIX_OPCODE:	q = LOCKREP_PREFIX;	break;      case FWAIT_OPCODE:	q = WAIT_PREFIX;	break;      case ADDR_PREFIX_OPCODE:	q = ADDR_PREFIX;	break;      case DATA_PREFIX_OPCODE:	q = DATA_PREFIX;	break;      }  if (i.prefix[q])    {      as_bad (_("same type of prefix used twice"));      return 0;    }  i.prefixes += 1;  i.prefix[q] = prefix;  return ret;}static voidset_code_flag (value)     int value;{  flag_code = value;  cpu_arch_flags &= ~(Cpu64 | CpuNo64);  cpu_arch_flags |= (flag_code == CODE_64BIT ? Cpu64 : CpuNo64);  if (value == CODE_64BIT && !(cpu_arch_flags & CpuSledgehammer))    {      as_bad (_("64bit mode not supported on this CPU."));    }  if (value == CODE_32BIT && !(cpu_arch_flags & Cpu386))    {      as_bad (_("32bit mode not supported on this CPU."));    }  stackop_size = '\0';}static voidset_16bit_gcc_code_flag (new_code_flag)     int new_code_flag;{  flag_code = new_code_flag;  cpu_arch_flags &= ~(Cpu64 | CpuNo64);  cpu_arch_flags |= (flag_code == CODE_64BIT ? Cpu64 : CpuNo64);  stackop_size = 'l';}static voidset_intel_syntax (syntax_flag)     int syntax_flag;{  /* Find out if register prefixing is specified.  */  int ask_naked_reg = 0;  SKIP_WHITESPACE ();  if (! is_end_of_line[(unsigned char) *input_line_pointer])    {      char *string = input_line_pointer;      int e = get_symbol_end ();      if (strcmp (string, "prefix") == 0)	ask_naked_reg = 1;      else if (strcmp (string, "noprefix") == 0)	ask_naked_reg = -1;      else	as_bad (_("bad argument to syntax directive."));      *input_line_pointer = e;    }  demand_empty_rest_of_line ();  intel_syntax = syntax_flag;  if (ask_naked_reg == 0)    {#ifdef BFD_ASSEMBLER      allow_naked_reg = (intel_syntax			 && (bfd_get_symbol_leading_char (stdoutput) != '\0'));#else      /* Conservative default.  */      allow_naked_reg = 0;#endif    }  else    allow_naked_reg = (ask_naked_reg < 0);}static voidset_cpu_arch (dummy)     int dummy ATTRIBUTE_UNUSED;{  SKIP_WHITESPACE ();  if (! is_end_of_line[(unsigned char) *input_line_pointer])    {      char *string = input_line_pointer;      int e = get_symbol_end ();      int i;      for (i = 0; cpu_arch[i].name; i++)	{	  if (strcmp (string, cpu_arch[i].name) == 0)	    {	      cpu_arch_name = cpu_arch[i].name;	      cpu_arch_flags = (cpu_arch[i].flags				| (flag_code == CODE_64BIT ? Cpu64 : CpuNo64));	      break;	    }	}      if (!cpu_arch[i].name)	as_bad (_("no such architecture: `%s'"), string);      *input_line_pointer = e;    }  else    as_bad (_("missing cpu architecture"));  no_cond_jump_promotion = 0;  if (*input_line_pointer == ','      && ! is_end_of_line[(unsigned char) input_line_pointer[1]])    {      char *string = ++input_line_pointer;      int e = get_symbol_end ();      if (strcmp (string, "nojumps") == 0)	no_cond_jump_promotion = 1;      else if (strcmp (string, "jumps") == 0)	;      else	as_bad (_("no such architecture modifier: `%s'"), string);      *input_line_pointer = e;    }  demand_empty_rest_of_line ();}const pseudo_typeS md_pseudo_table[] ={#if !defined(OBJ_AOUT) && !defined(USE_ALIGN_PTWO)  {"align", s_align_bytes, 0},#else  {"align", s_align_ptwo, 0},#endif  {"arch", set_cpu_arch, 0},#ifndef I386COFF  {"bss", s_bss, 0},#endif  {"ffloat", float_cons, 'f'},  {"dfloat", float_cons, 'd'},  {"tfloat", float_cons, 'x'},  {"value", cons, 2},  {"noopt", s_ignore, 0},  {"optim", s_ignore, 0},  {"code16gcc", set_16bit_gcc_code_flag, CODE_16BIT},  {"code16", set_code_flag, CODE_16BIT},  {"code32", set_code_flag, CODE_32BIT},  {"code64", set_code_flag, CODE_64BIT},  {"intel_syntax", set_intel_syntax, 1},  {"att_syntax", set_intel_syntax, 0},  {"file", dwarf2_directive_file, 0},  {"loc", dwarf2_directive_loc, 0},  {0, 0, 0}};/* For interface with expression ().  */extern char *input_line_pointer;/* Hash table for instruction mnemonic lookup.  */static struct hash_control *op_hash;/* Hash table for register lookup.  */static struct hash_control *reg_hash;#ifdef BFD_ASSEMBLERunsigned longi386_mach (){  if (!strcmp (default_arch, "x86_64"))    return bfd_mach_x86_64;  else if (!strcmp (default_arch, "i386"))    return bfd_mach_i386_i386;  else    as_fatal (_("Unknown architecture"));}#endifvoidmd_begin (){  const char *hash_err;  /* Initialize op_hash hash table.  */  op_hash = hash_new ();  {    register const template *optab;    register templates *core_optab;    /* Setup for loop.  */    optab = i386_optab;    core_optab = (templates *) xmalloc (sizeof (templates));    core_optab->start = optab;    while (1)      {	++optab;	if (optab->name == NULL	    || strcmp (optab->name, (optab - 1)->name) != 0)	  {	    /* different name --> ship out current template list;	       add to hash table; & begin anew.  */	    core_optab->end = optab;	    hash_err = hash_insert (op_hash,				    (optab - 1)->name,				    (PTR) core_optab);	    if (hash_err)	      {		as_fatal (_("Internal Error:  Can't hash %s: %s"),			  (optab - 1)->name,			  hash_err);	      }	    if (optab->name == NULL)	      break;	    core_optab = (templates *) xmalloc (sizeof (templates));	    core_optab->start = optab;	  }      }  }  /* Initialize reg_hash hash table.  */  reg_hash = hash_new ();  {    register const reg_entry *regtab;    for (regtab = i386_regtab;	 regtab < i386_regtab + sizeof (i386_regtab) / sizeof (i386_regtab[0]);	 regtab++)      {	hash_err = hash_insert (reg_hash, regtab->reg_name, (PTR) regtab);	if (hash_err)	  as_fatal (_("Internal Error:  Can't hash %s: %s"),		    regtab->reg_name,		    hash_err);      }  }  /* Fill in lexical tables:  mnemonic_chars, operand_chars.  */  {    register int c;    register char *p;    for (c = 0; c < 256; c++)      {	if (isdigit (c))	  {	    digit_chars[c] = c;	    mnemonic_chars[c] = c;	    register_chars[c] = c;	    operand_chars[c] = c;	  }	else if (islower (c))	  {	    mnemonic_chars[c] = c;	    register_chars[c] = c;	    operand_chars[c] = c;	  }	else if (isupper (c))	  {	    mnemonic_chars[c] = tolower (c);	    register_chars[c] = mnemonic_chars[c];	    operand_chars[c] = c;	  }	if (isalpha (c) || isdigit (c))	  identifier_chars[c] = c;	else if (c >= 128)	  {	    identifier_chars[c] = c;	    operand_chars[c] = c;	  }      }#ifdef LEX_AT    identifier_chars['@'] = '@';#endif    digit_chars['-'] = '-';

⌨️ 快捷键说明

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