tc-i386.c

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

C
2,311
字号
    if (found_reverse_match)      {	/* If we found a reverse match we must alter the opcode	   direction bit.  found_reverse_match holds bits to change	   (different for int & float insns).  */	i.tm.base_opcode ^= found_reverse_match;	i.tm.operand_types[0] = t->operand_types[1];	i.tm.operand_types[1] = t->operand_types[0];      }    /* Undo SYSV386_COMPAT brokenness when in Intel mode.  See i386.h  */    if (SYSV386_COMPAT	&& intel_syntax	&& (i.tm.base_opcode & 0xfffffde0) == 0xdce0)      i.tm.base_opcode ^= FloatR;    if (i.tm.opcode_modifier & FWait)      if (! add_prefix (FWAIT_OPCODE))	return;    /* Check string instruction segment overrides.  */    if ((i.tm.opcode_modifier & IsString) != 0 && i.mem_operands != 0)      {	int mem_op = (i.types[0] & AnyMem) ? 0 : 1;	if ((i.tm.operand_types[mem_op] & EsSeg) != 0)	  {	    if (i.seg[0] != NULL && i.seg[0] != &es)	      {		as_bad (_("`%s' operand %d must use `%%es' segment"),			i.tm.name,			mem_op + 1);		return;	      }	    /* There's only ever one segment override allowed per instruction.	       This instruction possibly has a legal segment override on the	       second operand, so copy the segment to where non-string	       instructions store it, allowing common code.  */	    i.seg[0] = i.seg[1];	  }	else if ((i.tm.operand_types[mem_op + 1] & EsSeg) != 0)	  {	    if (i.seg[1] != NULL && i.seg[1] != &es)	      {		as_bad (_("`%s' operand %d must use `%%es' segment"),			i.tm.name,			mem_op + 2);		return;	      }	  }      }    if (i.reg_operands && flag_code < CODE_64BIT)      {	int op;	for (op = i.operands; --op >= 0;)	  if ((i.types[op] & Reg)	      && (i.op[op].regs->reg_flags & (RegRex64|RegRex)))	    {	      as_bad (_("Extended register `%%%s' available only in 64bit mode."),		      i.op[op].regs->reg_name);	      return;	    }      }    /* If matched instruction specifies an explicit instruction mnemonic       suffix, use it.  */    if (i.tm.opcode_modifier & (Size16 | Size32 | Size64))      {	if (i.tm.opcode_modifier & Size16)	  i.suffix = WORD_MNEM_SUFFIX;	else if (i.tm.opcode_modifier & Size64)	  i.suffix = QWORD_MNEM_SUFFIX;	else	  i.suffix = LONG_MNEM_SUFFIX;      }    else if (i.reg_operands)      {	/* If there's no instruction mnemonic suffix we try to invent one	   based on register operands.  */	if (!i.suffix)	  {	    /* We take i.suffix from the last register operand specified,	       Destination register type is more significant than source	       register type.  */	    int op;	    for (op = i.operands; --op >= 0;)	      if ((i.types[op] & Reg)		  && !(i.tm.operand_types[op] & InOutPortReg))		{		  i.suffix = ((i.types[op] & Reg8) ? BYTE_MNEM_SUFFIX :			      (i.types[op] & Reg16) ? WORD_MNEM_SUFFIX :			      (i.types[op] & Reg64) ? QWORD_MNEM_SUFFIX :			      LONG_MNEM_SUFFIX);		  break;		}	  }	else if (i.suffix == BYTE_MNEM_SUFFIX)	  {	    int op;	    for (op = i.operands; --op >= 0;)	      {		/* If this is an eight bit register, it's OK.  If it's		   the 16 or 32 bit version of an eight bit register,		   we will just use the low portion, and that's OK too.  */		if (i.types[op] & Reg8)		  continue;		/* movzx and movsx should not generate this warning.  */		if (intel_syntax		    && (i.tm.base_opcode == 0xfb7			|| i.tm.base_opcode == 0xfb6			|| i.tm.base_opcode == 0x63			|| i.tm.base_opcode == 0xfbe			|| i.tm.base_opcode == 0xfbf))		  continue;		if ((i.types[op] & WordReg) && i.op[op].regs->reg_num < 4#if 0		    /* Check that the template allows eight bit regs		       This kills insns such as `orb $1,%edx', which		       maybe should be allowed.  */		    && (i.tm.operand_types[op] & (Reg8|InOutPortReg))#endif		    )		  {		    /* Prohibit these changes in the 64bit mode, since		       the lowering is more complicated.  */		    if (flag_code == CODE_64BIT			&& (i.tm.operand_types[op] & InOutPortReg) == 0)		      as_bad (_("Incorrect register `%%%s' used with`%c' suffix"),			      i.op[op].regs->reg_name,			      i.suffix);#if REGISTER_WARNINGS		    if (!quiet_warnings			&& (i.tm.operand_types[op] & InOutPortReg) == 0)		      as_warn (_("using `%%%s' instead of `%%%s' due to `%c' suffix"),			       (i.op[op].regs				+ (i.types[op] & Reg16				   ? REGNAM_AL - REGNAM_AX				   : REGNAM_AL - REGNAM_EAX))->reg_name,			       i.op[op].regs->reg_name,			       i.suffix);#endif		    continue;		  }		/* Any other register is bad.  */		if (i.types[op] & (Reg | RegMMX | RegXMM				   | SReg2 | SReg3				   | Control | Debug | Test				   | FloatReg | FloatAcc))		  {		    as_bad (_("`%%%s' not allowed with `%s%c'"),			    i.op[op].regs->reg_name,			    i.tm.name,			    i.suffix);		    return;		  }	      }	  }	else if (i.suffix == LONG_MNEM_SUFFIX)	  {	    int op;	    for (op = i.operands; --op >= 0;)	      /* Reject eight bit registers, except where the template		 requires them. (eg. movzb)  */	      if ((i.types[op] & Reg8) != 0		  && (i.tm.operand_types[op] & (Reg16 | Reg32 | Acc)) != 0)		{		  as_bad (_("`%%%s' not allowed with `%s%c'"),			  i.op[op].regs->reg_name,			  i.tm.name,			  i.suffix);		  return;		}	      /* Warn if the e prefix on a general reg is missing.  */	      else if ((!quiet_warnings || flag_code == CODE_64BIT)		       && (i.types[op] & Reg16) != 0		       && (i.tm.operand_types[op] & (Reg32|Acc)) != 0)		{		  /* Prohibit these changes in the 64bit mode, since		     the lowering is more complicated.  */		  if (flag_code == CODE_64BIT)		    as_bad (_("Incorrect register `%%%s' used with`%c' suffix"),			    i.op[op].regs->reg_name,			    i.suffix);#if REGISTER_WARNINGS		  else		    as_warn (_("using `%%%s' instead of `%%%s' due to `%c' suffix"),			     (i.op[op].regs + REGNAM_EAX - REGNAM_AX)->reg_name,			     i.op[op].regs->reg_name,			     i.suffix);#endif		}	      /* Warn if the r prefix on a general reg is missing.  */	      else if ((i.types[op] & Reg64) != 0		       && (i.tm.operand_types[op] & (Reg32|Acc)) != 0)		{		  as_bad (_("Incorrect register `%%%s' used with`%c' suffix"),			  i.op[op].regs->reg_name,			  i.suffix);		}	  }	else if (i.suffix == QWORD_MNEM_SUFFIX)	  {	    int op;	    for (op = i.operands; --op >= 0; )	      /* Reject eight bit registers, except where the template		 requires them. (eg. movzb)  */	      if ((i.types[op] & Reg8) != 0		  && (i.tm.operand_types[op] & (Reg16|Reg32|Acc)) != 0)		{		  as_bad (_("`%%%s' not allowed with `%s%c'"),			  i.op[op].regs->reg_name,			  i.tm.name,			  i.suffix);		  return;		}	      /* Warn if the e prefix on a general reg is missing.  */	      else if (((i.types[op] & Reg16) != 0		        || (i.types[op] & Reg32) != 0)		       && (i.tm.operand_types[op] & (Reg32|Acc)) != 0)		{		  /* Prohibit these changes in the 64bit mode, since		     the lowering is more complicated.  */		  as_bad (_("Incorrect register `%%%s' used with`%c' suffix"),			  i.op[op].regs->reg_name,			  i.suffix);		}	  }	else if (i.suffix == WORD_MNEM_SUFFIX)	  {	    int op;	    for (op = i.operands; --op >= 0;)	      /* Reject eight bit registers, except where the template		 requires them. (eg. movzb)  */	      if ((i.types[op] & Reg8) != 0		  && (i.tm.operand_types[op] & (Reg16|Reg32|Acc)) != 0)		{		  as_bad (_("`%%%s' not allowed with `%s%c'"),			  i.op[op].regs->reg_name,			  i.tm.name,			  i.suffix);		  return;		}	      /* Warn if the e prefix on a general reg is present.  */	      else if ((!quiet_warnings || flag_code == CODE_64BIT)		       && (i.types[op] & Reg32) != 0		       && (i.tm.operand_types[op] & (Reg16|Acc)) != 0)		{		  /* Prohibit these changes in the 64bit mode, since		     the lowering is more complicated.  */		  if (flag_code == CODE_64BIT)		    as_bad (_("Incorrect register `%%%s' used with`%c' suffix"),			    i.op[op].regs->reg_name,			    i.suffix);		  else#if REGISTER_WARNINGS		    as_warn (_("using `%%%s' instead of `%%%s' due to `%c' suffix"),			     (i.op[op].regs + REGNAM_AX - REGNAM_EAX)->reg_name,			     i.op[op].regs->reg_name,			     i.suffix);#endif		}	  }	else if (intel_syntax && (i.tm.opcode_modifier & IgnoreSize))	  /* Do nothing if the instruction is going to ignore the prefix.  */	  ;	else	  abort ();      }    else if ((i.tm.opcode_modifier & DefaultSize) && !i.suffix)      {	i.suffix = stackop_size;      }    /* Make still unresolved immediate matches conform to size of immediate       given in i.suffix.  Note: overlap2 cannot be an immediate!  */    if ((overlap0 & (Imm8 | Imm8S | Imm16 | Imm32 | Imm32S))	&& overlap0 != Imm8 && overlap0 != Imm8S	&& overlap0 != Imm16 && overlap0 != Imm32S	&& overlap0 != Imm32 && overlap0 != Imm64)      {	if (i.suffix)	  {	    overlap0 &= (i.suffix == BYTE_MNEM_SUFFIX ? (Imm8 | Imm8S) :			(i.suffix == WORD_MNEM_SUFFIX ? Imm16 :			(i.suffix == QWORD_MNEM_SUFFIX ? Imm64 | Imm32S : Imm32)));	  }	else if (overlap0 == (Imm16 | Imm32S | Imm32)		 || overlap0 == (Imm16 | Imm32)		 || overlap0 == (Imm16 | Imm32S))	  {	    overlap0 =	      ((flag_code == CODE_16BIT) ^ (i.prefix[DATA_PREFIX] != 0)) ? Imm16 : Imm32S;	  }	if (overlap0 != Imm8 && overlap0 != Imm8S	    && overlap0 != Imm16 && overlap0 != Imm32S	    && overlap0 != Imm32 && overlap0 != Imm64)	  {	    as_bad (_("no instruction mnemonic suffix given; can't determine immediate size"));	    return;	  }      }    if ((overlap1 & (Imm8 | Imm8S | Imm16 | Imm32S | Imm32))	&& overlap1 != Imm8 && overlap1 != Imm8S	&& overlap1 != Imm16 && overlap1 != Imm32S	&& overlap1 != Imm32 && overlap1 != Imm64)      {	if (i.suffix)	  {	    overlap1 &= (i.suffix == BYTE_MNEM_SUFFIX ? (Imm8 | Imm8S) :			(i.suffix == WORD_MNEM_SUFFIX ? Imm16 :			(i.suffix == QWORD_MNEM_SUFFIX ? Imm64 | Imm32S : Imm32)));	  }	else if (overlap1 == (Imm16 | Imm32 | Imm32S)		 || overlap1 == (Imm16 | Imm32)		 || overlap1 == (Imm16 | Imm32S))	  {	    overlap1 =	      ((flag_code == CODE_16BIT) ^ (i.prefix[DATA_PREFIX] != 0)) ? Imm16 : Imm32S;	  }	if (overlap1 != Imm8 && overlap1 != Imm8S	    && overlap1 != Imm16 && overlap1 != Imm32S	    && overlap1 != Imm32 && overlap1 != Imm64)	  {	    as_bad (_("no instruction mnemonic suffix given; can't determine immediate size %x %c"),overlap1, i.suffix);	    return;	  }      }    assert ((overlap2 & Imm) == 0);    i.types[0] = overlap0;    if (overlap0 & ImplicitRegister)      i.reg_operands--;    if (overlap0 & Imm1)      i.imm_operands = 0;	/* kludge for shift insns.  */    i.types[1] = overlap1;    if (overlap1 & ImplicitRegister)      i.reg_operands--;    i.types[2] = overlap2;    if (overlap2 & ImplicitRegister)      i.reg_operands--;    /* Finalize opcode.  First, we change the opcode based on the operand       size given by i.suffix:  We need not change things for byte insns.  */    if (!i.suffix && (i.tm.opcode_modifier & W))      {	as_bad (_("no instruction mnemonic suffix given and no register operands; can't size instruction"));	return;      }    /* For movzx and movsx, need to check the register type.  */    if (intel_syntax	&& (i.tm.base_opcode == 0xfb6 || i.tm.base_opcode == 0xfbe))      if (i.suffix && i.suffix == BYTE_MNEM_SUFFIX)	{	  unsigned int prefix = DATA_PREFIX_OPCODE;	  if ((i.op[1].regs->reg_type & Reg16) != 0)	    if (!add_prefix (prefix))	      return;	}    if (i.suffix && i.suffix != BYTE_MNEM_SUFFIX)      {	/* It's not a byte, select word/dword operation.  */	if (i.tm.opcode_modifier & W)	  {	    if (i.tm.opcode_modifier & ShortForm)	      i.tm.base_opcode |= 8;	    else	      i.tm.base_opcode |= 1;	  }	/* Now select between word & dword operations via the operand	   size prefix, except for instructions that will ignore this	   prefix anyway.  */	if (i.suffix != QWORD_MNEM_SUFFIX	    && (i.suffix == LONG_MNEM_SUFFIX) == (flag_code == CODE_16BIT)	    && !(i.tm.opcode_modifier & IgnoreSize))	  {	    unsigned int prefix = DATA_PREFIX_OPCODE;	    if (i.tm.opcode_modifier & JumpByte) /* jcxz, loop */	      prefix = ADDR_PREFIX_OPCODE;	    if (! add_prefix (prefix))	      return;	  }	/* Set mode64 for an operand.  */	if (i.suffix == QWORD_MNEM_SUFFIX	    && !(i.tm.opcode_modifier & NoRex64))	  {	    i.rex.mode64 = 1;	    if (flag_code < CODE_64BIT)	      {		as_bad (_("64bit operations available only in 64bit modes."));		return;	      }	  }	/* Size floating point instruction.  */	if (i.suffix == LONG_MNEM_SUFFIX)	  {	    if (i.tm.opcode_modifier & FloatMF)	      i.tm.base_opcode ^= 4;	  }      }    if (i.tm.opcode_modifier & ImmExt)      {	/* These AMD 3DNow! and Intel Katmai New Instructions have an	   opcode suffix which is coded in the same place as an 8-bit	   immediate field would be.  Here we fake an 8-bit immediate	   operand from the opcode suffix stored in tm.extension_opcode.  */	expressionS *exp;	assert (i.imm_operands == 0 && i.operands <= 2 && 2 < MAX_OPERANDS);	exp = &im_expressions[i.imm_operands++];	i.op[i.operands].imms = exp;	i.types[i.operands++] = Imm8;	exp->X_op = O_constant;	exp->X_add_number = i.tm.extension_opcode;	i.tm.extension_opcode = None;      }    /* For insns with operands there are more diddles to do to the opcode.  */    if (i.operands)      {	/* Default segment register this instruction will use	   for memory accesses.  0 means unknown.	   This is only for optimizing out unnecessary segment overrides.  */	const seg_entry *default_seg = 0;	/* The imul $imm, %reg instruction is converted into	   imul $imm, %reg, %reg, and the clr %reg instruction	   is converted into xor %reg, %reg.  */	if (i.tm.opcode_modifier & regKludge)	  {	    unsigned int first_reg_op = (i.types[0] & Reg) ? 0 : 1;	    /* Pretend we saw the extra register operand.  */	    assert (i.op[first_reg_op + 1].regs == 0);	    i.op[first_reg_op + 1].regs = i.op[first_reg_op].regs;	    i.types[first_reg_op + 1] = i.types[first_reg_op];	    i.reg_operands = 2;	  }	if (i.tm.opcode_modifier & ShortForm)	  {	    /* The register or float register operand is in operand 0 or 1.  */	    unsigned int op = (i.types[0] & (Reg | FloatReg)) ? 0 : 1;	    /* Register goes in low 3 

⌨️ 快捷键说明

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