tc-i386.c

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

C
2,311
字号
    identifier_chars['_'] = '_';    identifier_chars['.'] = '.';    for (p = operand_special_chars; *p != '\0'; p++)      operand_chars[(unsigned char) *p] = *p;  }#if defined (OBJ_ELF) || defined (OBJ_MAYBE_ELF)  if (OUTPUT_FLAVOR == bfd_target_elf_flavour)    {      record_alignment (text_section, 2);      record_alignment (data_section, 2);      record_alignment (bss_section, 2);    }#endif}voidi386_print_statistics (file)     FILE *file;{  hash_print_statistics (file, "i386 opcode", op_hash);  hash_print_statistics (file, "i386 register", reg_hash);}#ifdef DEBUG386/* Debugging routines for md_assemble.  */static void pi PARAMS ((char *, i386_insn *));static void pte PARAMS ((template *));static void pt PARAMS ((unsigned int));static void pe PARAMS ((expressionS *));static void ps PARAMS ((symbolS *));static voidpi (line, x)     char *line;     i386_insn *x;{  unsigned int i;  fprintf (stdout, "%s: template ", line);  pte (&x->tm);  fprintf (stdout, "  address: base %s  index %s  scale %x\n",	   x->base_reg ? x->base_reg->reg_name : "none",	   x->index_reg ? x->index_reg->reg_name : "none",	   x->log2_scale_factor);  fprintf (stdout, "  modrm:  mode %x  reg %x  reg/mem %x\n",	   x->rm.mode, x->rm.reg, x->rm.regmem);  fprintf (stdout, "  sib:  base %x  index %x  scale %x\n",	   x->sib.base, x->sib.index, x->sib.scale);  fprintf (stdout, "  rex: 64bit %x  extX %x  extY %x  extZ %x\n",	   x->rex.mode64, x->rex.extX, x->rex.extY, x->rex.extZ);  for (i = 0; i < x->operands; i++)    {      fprintf (stdout, "    #%d:  ", i + 1);      pt (x->types[i]);      fprintf (stdout, "\n");      if (x->types[i]	  & (Reg | SReg2 | SReg3 | Control | Debug | Test | RegMMX | RegXMM))	fprintf (stdout, "%s\n", x->op[i].regs->reg_name);      if (x->types[i] & Imm)	pe (x->op[i].imms);      if (x->types[i] & Disp)	pe (x->op[i].disps);    }}static voidpte (t)     template *t;{  unsigned int i;  fprintf (stdout, " %d operands ", t->operands);  fprintf (stdout, "opcode %x ", t->base_opcode);  if (t->extension_opcode != None)    fprintf (stdout, "ext %x ", t->extension_opcode);  if (t->opcode_modifier & D)    fprintf (stdout, "D");  if (t->opcode_modifier & W)    fprintf (stdout, "W");  fprintf (stdout, "\n");  for (i = 0; i < t->operands; i++)    {      fprintf (stdout, "    #%d type ", i + 1);      pt (t->operand_types[i]);      fprintf (stdout, "\n");    }}static voidpe (e)     expressionS *e;{  fprintf (stdout, "    operation     %d\n", e->X_op);  fprintf (stdout, "    add_number    %ld (%lx)\n",	   (long) e->X_add_number, (long) e->X_add_number);  if (e->X_add_symbol)    {      fprintf (stdout, "    add_symbol    ");      ps (e->X_add_symbol);      fprintf (stdout, "\n");    }  if (e->X_op_symbol)    {      fprintf (stdout, "    op_symbol    ");      ps (e->X_op_symbol);      fprintf (stdout, "\n");    }}static voidps (s)     symbolS *s;{  fprintf (stdout, "%s type %s%s",	   S_GET_NAME (s),	   S_IS_EXTERNAL (s) ? "EXTERNAL " : "",	   segment_name (S_GET_SEGMENT (s)));}struct type_name  {    unsigned int mask;    char *tname;  }type_names[] ={  { Reg8, "r8" },  { Reg16, "r16" },  { Reg32, "r32" },  { Reg64, "r64" },  { Imm8, "i8" },  { Imm8S, "i8s" },  { Imm16, "i16" },  { Imm32, "i32" },  { Imm32S, "i32s" },  { Imm64, "i64" },  { Imm1, "i1" },  { BaseIndex, "BaseIndex" },  { Disp8, "d8" },  { Disp16, "d16" },  { Disp32, "d32" },  { Disp32S, "d32s" },  { Disp64, "d64" },  { InOutPortReg, "InOutPortReg" },  { ShiftCount, "ShiftCount" },  { Control, "control reg" },  { Test, "test reg" },  { Debug, "debug reg" },  { FloatReg, "FReg" },  { FloatAcc, "FAcc" },  { SReg2, "SReg2" },  { SReg3, "SReg3" },  { Acc, "Acc" },  { JumpAbsolute, "Jump Absolute" },  { RegMMX, "rMMX" },  { RegXMM, "rXMM" },  { EsSeg, "es" },  { 0, "" }};static voidpt (t)     unsigned int t;{  register struct type_name *ty;  for (ty = type_names; ty->mask; ty++)    if (t & ty->mask)      fprintf (stdout, "%s, ", ty->tname);  fflush (stdout);}#endif /* DEBUG386 */inttc_i386_force_relocation (fixp)     struct fix *fixp;{#ifdef BFD_ASSEMBLER  if (fixp->fx_r_type == BFD_RELOC_VTABLE_INHERIT      || fixp->fx_r_type == BFD_RELOC_VTABLE_ENTRY)    return 1;  return 0;#else  /* For COFF.  */  return fixp->fx_r_type == 7;#endif}#ifdef BFD_ASSEMBLERstatic bfd_reloc_code_real_typereloc (size, pcrel, sign, other)     int size;     int pcrel;     int sign;     bfd_reloc_code_real_type other;{  if (other != NO_RELOC)    return other;  if (pcrel)    {      if (!sign)	as_bad (_("There are no unsigned pc-relative relocations"));      switch (size)	{	case 1: return BFD_RELOC_8_PCREL;	case 2: return BFD_RELOC_16_PCREL;	case 4: return BFD_RELOC_32_PCREL;	}      as_bad (_("can not do %d byte pc-relative relocation"), size);    }  else    {      if (sign)	switch (size)	  {	  case 4: return BFD_RELOC_X86_64_32S;	  }      else	switch (size)	  {	  case 1: return BFD_RELOC_8;	  case 2: return BFD_RELOC_16;	  case 4: return BFD_RELOC_32;	  case 8: return BFD_RELOC_64;	  }      as_bad (_("can not do %s %d byte relocation"),	      sign ? "signed" : "unsigned", size);    }  abort ();  return BFD_RELOC_NONE;}/* Here we decide which fixups can be adjusted to make them relative to   the beginning of the section instead of the symbol.  Basically we need   to make sure that the dynamic relocations are done correctly, so in   some cases we force the original symbol to be used.  */inttc_i386_fix_adjustable (fixP)     fixS *fixP;{#if defined (OBJ_ELF) || defined (OBJ_MAYBE_ELF)  /* Prevent all adjustments to global symbols, or else dynamic     linking will not work correctly.  */  if (S_IS_EXTERNAL (fixP->fx_addsy)      || S_IS_WEAK (fixP->fx_addsy))    return 0;#endif  /* adjust_reloc_syms doesn't know about the GOT.  */  if (fixP->fx_r_type == BFD_RELOC_386_GOTOFF      || fixP->fx_r_type == BFD_RELOC_386_PLT32      || fixP->fx_r_type == BFD_RELOC_386_GOT32      || fixP->fx_r_type == BFD_RELOC_X86_64_PLT32      || fixP->fx_r_type == BFD_RELOC_X86_64_GOT32      || fixP->fx_r_type == BFD_RELOC_X86_64_GOTPCREL      || fixP->fx_r_type == BFD_RELOC_VTABLE_INHERIT      || fixP->fx_r_type == BFD_RELOC_VTABLE_ENTRY)    return 0;  return 1;}#else#define reloc(SIZE,PCREL,SIGN,OTHER)	0#define BFD_RELOC_16			0#define BFD_RELOC_32			0#define BFD_RELOC_16_PCREL		0#define BFD_RELOC_32_PCREL		0#define BFD_RELOC_386_PLT32		0#define BFD_RELOC_386_GOT32		0#define BFD_RELOC_386_GOTOFF		0#define BFD_RELOC_X86_64_PLT32		0#define BFD_RELOC_X86_64_GOT32		0#define BFD_RELOC_X86_64_GOTPCREL	0#endifstatic int intel_float_operand PARAMS ((char *mnemonic));static intintel_float_operand (mnemonic)     char *mnemonic;{  if (mnemonic[0] == 'f' && mnemonic[1] == 'i')    return 2;  if (mnemonic[0] == 'f')    return 1;  return 0;}/* This is the guts of the machine-dependent assembler.  LINE points to a   machine dependent instruction.  This function is supposed to emit   the frags/bytes it assembles to.  */voidmd_assemble (line)     char *line;{  /* Points to template once we've found it.  */  const template *t;  int j;  char mnemonic[MAX_MNEM_SIZE];  /* Initialize globals.  */  memset (&i, '\0', sizeof (i));  for (j = 0; j < MAX_OPERANDS; j++)    i.reloc[j] = NO_RELOC;  memset (disp_expressions, '\0', sizeof (disp_expressions));  memset (im_expressions, '\0', sizeof (im_expressions));  save_stack_p = save_stack;  /* First parse an instruction mnemonic & call i386_operand for the operands.     We assume that the scrubber has arranged it so that line[0] is the valid     start of a (possibly prefixed) mnemonic.  */  {    char *l = line;    char *token_start = l;    char *mnem_p;    /* Non-zero if we found a prefix only acceptable with string insns.  */    const char *expecting_string_instruction = NULL;    while (1)      {	mnem_p = mnemonic;	while ((*mnem_p = mnemonic_chars[(unsigned char) *l]) != 0)	  {	    mnem_p++;	    if (mnem_p >= mnemonic + sizeof (mnemonic))	      {		as_bad (_("no such instruction: `%s'"), token_start);		return;	      }	    l++;	  }	if (!is_space_char (*l)	    && *l != END_OF_INSN	    && *l != PREFIX_SEPARATOR)	  {	    as_bad (_("invalid character %s in mnemonic"),		    output_invalid (*l));	    return;	  }	if (token_start == l)	  {	    if (*l == PREFIX_SEPARATOR)	      as_bad (_("expecting prefix; got nothing"));	    else	      as_bad (_("expecting mnemonic; got nothing"));	    return;	  }	/* Look up instruction (or prefix) via hash table.  */	current_templates = hash_find (op_hash, mnemonic);	if (*l != END_OF_INSN	    && (! is_space_char (*l) || l[1] != END_OF_INSN)	    && current_templates	    && (current_templates->start->opcode_modifier & IsPrefix))	  {	    /* If we are in 16-bit mode, do not allow addr16 or data16.	       Similarly, in 32-bit mode, do not allow addr32 or data32.  */	    if ((current_templates->start->opcode_modifier & (Size16 | Size32))		&& (((current_templates->start->opcode_modifier & Size32) != 0)		    ^ (flag_code == CODE_16BIT)))	      {		as_bad (_("redundant %s prefix"),			current_templates->start->name);		return;	      }	    /* Add prefix, checking for repeated prefixes.  */	    switch (add_prefix (current_templates->start->base_opcode))	      {	      case 0:		return;	      case 2:		expecting_string_instruction = current_templates->start->name;		break;	      }	    /* Skip past PREFIX_SEPARATOR and reset token_start.  */	    token_start = ++l;	  }	else	  break;      }    if (!current_templates)      {	/* See if we can get a match by trimming off a suffix.  */	switch (mnem_p[-1])	  {	  case WORD_MNEM_SUFFIX:	  case BYTE_MNEM_SUFFIX:	  case QWORD_MNEM_SUFFIX:	    i.suffix = mnem_p[-1];	    mnem_p[-1] = '\0';	    current_templates = hash_find (op_hash, mnemonic);	    break;	  case SHORT_MNEM_SUFFIX:	  case LONG_MNEM_SUFFIX:	    if (!intel_syntax)	      {		i.suffix = mnem_p[-1];		mnem_p[-1] = '\0';		current_templates = hash_find (op_hash, mnemonic);	      }	    break;	  /* Intel Syntax.  */	  case 'd':	    if (intel_syntax)	      {		if (intel_float_operand (mnemonic))		  i.suffix = SHORT_MNEM_SUFFIX;		else		  i.suffix = LONG_MNEM_SUFFIX;		mnem_p[-1] = '\0';		current_templates = hash_find (op_hash, mnemonic);	      }	    break;	  }	if (!current_templates)	  {	    as_bad (_("no such instruction: `%s'"), token_start);	    return;	  }      }    /* Check if instruction is supported on specified architecture.  */    if (cpu_arch_flags != 0)      {	if ((current_templates->start->cpu_flags & ~(Cpu64 | CpuNo64))	    & ~(cpu_arch_flags & ~(Cpu64 | CpuNo64)))	  {	    as_warn (_("`%s' is not supported on `%s'"),		     current_templates->start->name, cpu_arch_name);	  }	else if ((Cpu386 & ~cpu_arch_flags) && (flag_code != CODE_16BIT))	  {	    as_warn (_("use .code16 to ensure correct addressing mode"));	  }      }    /* Check for rep/repne without a string instruction.  */    if (expecting_string_instruction	&& !(current_templates->start->opcode_modifier & IsString))      {	as_bad (_("expecting string instruction after `%s'"),		expecting_string_instruction);	return;      }    /* There may be operands to parse.  */    if (*l != END_OF_INSN)      {

⌨️ 快捷键说明

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