📄 i386.h
字号:
/* opcode/i386.h -- Intel 80386 opcode table Copyright 1989, 1991, 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004 Free Software Foundation, Inc. This file is part of GAS, the GNU Assembler, and GDB, the GNU Debugger. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *//* The SystemV/386 SVR3.2 assembler, and probably all AT&T derived ix86 Unix assemblers, generate floating point instructions with reversed source and destination registers in certain cases. Unfortunately, gcc and possibly many other programs use this reversed syntax, so we're stuck with it. eg. `fsub %st(3),%st' results in st = st - st(3) as expected, but `fsub %st,%st(3)' results in st(3) = st - st(3), rather than the expected st(3) = st(3) - st This happens with all the non-commutative arithmetic floating point operations with two register operands, where the source register is %st, and destination register is %st(i). See FloatDR below. The affected opcode map is dceX, dcfX, deeX, defX. */#ifndef SYSV386_COMPAT/* Set non-zero for broken, compatible instructions. Set to zero for non-broken opcodes at your peril. gcc generates SystemV/386 compatible instructions. */#define SYSV386_COMPAT 1#endif#ifndef OLDGCC_COMPAT/* Set non-zero to cater for old (<= 2.8.1) versions of gcc that could generate nonsense fsubp, fsubrp, fdivp and fdivrp with operands reversed. */#define OLDGCC_COMPAT SYSV386_COMPAT#endifstatic const template i386_optab[] ={#define X None#define NoSuf (No_bSuf|No_wSuf|No_lSuf|No_sSuf|No_xSuf|No_qSuf)#define b_Suf (No_wSuf|No_lSuf|No_sSuf|No_xSuf|No_qSuf)#define w_Suf (No_bSuf|No_lSuf|No_sSuf|No_xSuf|No_qSuf)#define l_Suf (No_bSuf|No_wSuf|No_sSuf|No_xSuf|No_qSuf)#define q_Suf (No_bSuf|No_wSuf|No_sSuf|No_lSuf|No_xSuf)#define x_Suf (No_bSuf|No_wSuf|No_sSuf|No_lSuf|No_qSuf)#define bw_Suf (No_lSuf|No_sSuf|No_xSuf|No_qSuf)#define bl_Suf (No_wSuf|No_sSuf|No_xSuf|No_qSuf)#define wl_Suf (No_bSuf|No_sSuf|No_xSuf|No_qSuf)#define wlq_Suf (No_bSuf|No_sSuf|No_xSuf)#define lq_Suf (No_bSuf|No_wSuf|No_sSuf|No_xSuf)#define wq_Suf (No_bSuf|No_lSuf|No_sSuf|No_xSuf)#define sl_Suf (No_bSuf|No_wSuf|No_xSuf|No_qSuf)#define sldx_Suf (No_bSuf|No_wSuf|No_qSuf)#define bwl_Suf (No_sSuf|No_xSuf|No_qSuf)#define bwlq_Suf (No_sSuf|No_xSuf)#define FP (NoSuf|IgnoreSize)#define l_FP (l_Suf|IgnoreSize)#define x_FP (x_Suf|IgnoreSize)#define sl_FP (sl_Suf|IgnoreSize)#if SYSV386_COMPAT/* Someone forgot that the FloatR bit reverses the operation when not equal to the FloatD bit. ie. Changing only FloatD results in the destination being swapped *and* the direction being reversed. */#define FloatDR FloatD#else#define FloatDR (FloatD|FloatR)#endif/* Move instructions. */#define MOV_AX_DISP32 0xa0/* In the 64bit mode the short form mov immediate is redefined to have 64bit displacement value. */{ "mov", 2, 0xa0, X, CpuNo64,bwlq_Suf|D|W, { Disp16|Disp32, Acc, 0 } },{ "mov", 2, 0x88, X, 0, bwlq_Suf|D|W|Modrm, { Reg, Reg|AnyMem, 0} },/* In the 64bit mode the short form mov immediate is redefined to have 64bit displacement value. */{ "mov", 2, 0xb0, X, 0, bwl_Suf|W|ShortForm, { EncImm, Reg8|Reg16|Reg32, 0 } },{ "mov", 2, 0xc6, 0, 0, bwlq_Suf|W|Modrm, { EncImm, Reg|AnyMem, 0 } },{ "mov", 2, 0xb0, X, Cpu64, q_Suf|W|ShortForm, { Imm64, Reg64, 0 } },/* The segment register moves accept WordReg so that a segment register can be copied to a 32 bit register, and vice versa, without using a size prefix. When moving to a 32 bit register, the upper 16 bits are set to an implementation defined value (on the Pentium Pro, the implementation defined value is zero). */{ "mov", 2, 0x8c, X, 0, wl_Suf|Modrm, { SReg2, WordReg|WordMem, 0 } },{ "mov", 2, 0x8c, X, Cpu386, wl_Suf|Modrm, { SReg3, WordReg|WordMem, 0 } },{ "mov", 2, 0x8e, X, 0, wl_Suf|Modrm|IgnoreSize, { WordReg|WordMem, SReg2, 0 } },{ "mov", 2, 0x8e, X, Cpu386, wl_Suf|Modrm|IgnoreSize, { WordReg|WordMem, SReg3, 0 } },/* Move to/from control debug registers. In the 16 or 32bit modes they are 32bit. In the 64bit mode they are 64bit.*/{ "mov", 2, 0x0f20, X, Cpu386|CpuNo64, l_Suf|D|Modrm|IgnoreSize,{ Control, Reg32|InvMem, 0} },{ "mov", 2, 0x0f20, X, Cpu64, q_Suf|D|Modrm|IgnoreSize|NoRex64,{ Control, Reg64|InvMem, 0} },{ "mov", 2, 0x0f21, X, Cpu386|CpuNo64, l_Suf|D|Modrm|IgnoreSize,{ Debug, Reg32|InvMem, 0} },{ "mov", 2, 0x0f21, X, Cpu64, q_Suf|D|Modrm|IgnoreSize|NoRex64,{ Debug, Reg64|InvMem, 0} },{ "mov", 2, 0x0f24, X, Cpu386, l_Suf|D|Modrm|IgnoreSize, { Test, Reg32|InvMem, 0} },{ "movabs",2, 0xa0, X, Cpu64, bwlq_Suf|D|W, { Disp64, Acc, 0 } },{ "movabs",2, 0xb0, X, Cpu64, q_Suf|W|ShortForm, { Imm64, Reg64, 0 } },/* Move with sign extend. *//* "movsbl" & "movsbw" must not be unified into "movsb" to avoid conflict with the "movs" string move instruction. */{"movsbl", 2, 0x0fbe, X, Cpu386, NoSuf|Modrm, { Reg8|ByteMem, Reg32, 0} },{"movsbw", 2, 0x0fbe, X, Cpu386, NoSuf|Modrm, { Reg8|ByteMem, Reg16, 0} },{"movswl", 2, 0x0fbf, X, Cpu386, NoSuf|Modrm, { Reg16|ShortMem,Reg32, 0} },{"movsbq", 2, 0x0fbe, X, Cpu64, NoSuf|Modrm|Rex64, { Reg8|ByteMem, Reg64, 0} },{"movswq", 2, 0x0fbf, X, Cpu64, NoSuf|Modrm|Rex64, { Reg16|ShortMem,Reg64, 0} },{"movslq", 2, 0x63, X, Cpu64, NoSuf|Modrm|Rex64, { Reg32|WordMem, Reg64, 0} },/* Intel Syntax next 5 insns */{"movsx", 2, 0x0fbe, X, Cpu386, b_Suf|Modrm, { Reg8|ByteMem, WordReg, 0} },{"movsx", 2, 0x0fbf, X, Cpu386, w_Suf|Modrm, { Reg16|ShortMem, Reg32, 0} },{"movsx", 2, 0x0fbe, X, Cpu64, b_Suf|Modrm|Rex64, { Reg8|ByteMem, Reg64, 0} },{"movsx", 2, 0x0fbf, X, Cpu64, w_Suf|Modrm|Rex64, { Reg16|ShortMem, Reg64, 0} },{"movsx", 2, 0x63, X, Cpu64, l_Suf|Modrm|Rex64, { Reg32|WordMem, Reg64, 0} },/* Move with zero extend. */{"movzb", 2, 0x0fb6, X, Cpu386, wl_Suf|Modrm, { Reg8|ByteMem, WordReg, 0} },{"movzwl", 2, 0x0fb7, X, Cpu386, NoSuf|Modrm, { Reg16|ShortMem, Reg32, 0} },/* These instructions are not particulary usefull, since the zero extend 32->64 is implicit, but we can encode them. */{"movzbq", 2, 0x0fb6, X, Cpu64, NoSuf|Modrm|Rex64, { Reg8|ByteMem, Reg64, 0} },{"movzwq", 2, 0x0fb7, X, Cpu64, NoSuf|Modrm|Rex64, { Reg16|ShortMem, Reg64, 0} },/* Intel Syntax next 4 insns */{"movzx", 2, 0x0fb6, X, Cpu386, b_Suf|Modrm, { Reg8|ByteMem, WordReg, 0} },{"movzx", 2, 0x0fb7, X, Cpu386, w_Suf|Modrm, { Reg16|ShortMem, Reg32, 0} },/* These instructions are not particulary usefull, since the zero extend 32->64 is implicit, but we can encode them. */{"movzx", 2, 0x0fb6, X, Cpu64, b_Suf|Modrm|Rex64, { Reg8|ByteMem, Reg64, 0} },{"movzx", 2, 0x0fb7, X, Cpu64, w_Suf|Modrm|Rex64, { Reg16|ShortMem, Reg64, 0} },/* Push instructions. */{"push", 1, 0x50, X, CpuNo64, wl_Suf|ShortForm|DefaultSize, { WordReg, 0, 0 } },{"push", 1, 0xff, 6, CpuNo64, wl_Suf|Modrm|DefaultSize, { WordReg|WordMem, 0, 0 } },{"push", 1, 0x6a, X, Cpu186|CpuNo64, wl_Suf|DefaultSize, { Imm8S, 0, 0} },{"push", 1, 0x68, X, Cpu186|CpuNo64, wl_Suf|DefaultSize, { Imm16|Imm32, 0, 0} },{"push", 1, 0x06, X, CpuNo64, wl_Suf|Seg2ShortForm|DefaultSize, { SReg2, 0, 0 } },{"push", 1, 0x0fa0, X, Cpu386|CpuNo64, wl_Suf|Seg3ShortForm|DefaultSize, { SReg3, 0, 0 } },/* In 64bit mode, the operand size is implicitly 64bit. */{"push", 1, 0x50, X, Cpu64, wq_Suf|ShortForm|DefaultSize|NoRex64, { Reg16|Reg64, 0, 0 } },{"push", 1, 0xff, 6, Cpu64, wq_Suf|Modrm|DefaultSize|NoRex64, { Reg16|Reg64|WordMem, 0, 0 } },{"push", 1, 0x6a, X, Cpu64, wq_Suf|DefaultSize|NoRex64, { Imm8S, 0, 0} },{"push", 1, 0x68, X, Cpu64, wq_Suf|DefaultSize|NoRex64, { Imm32S|Imm16, 0, 0} },{"push", 1, 0x0fa0, X, Cpu64, wq_Suf|Seg3ShortForm|DefaultSize|NoRex64, { SReg3, 0, 0 } },{"pusha", 0, 0x60, X, Cpu186|CpuNo64, wl_Suf|DefaultSize, { 0, 0, 0 } },/* Pop instructions. */{"pop", 1, 0x58, X, CpuNo64, wl_Suf|ShortForm|DefaultSize, { WordReg, 0, 0 } },{"pop", 1, 0x8f, 0, CpuNo64, wl_Suf|Modrm|DefaultSize, { WordReg|WordMem, 0, 0 } },#define POP_SEG_SHORT 0x07{"pop", 1, 0x07, X, CpuNo64, wl_Suf|Seg2ShortForm|DefaultSize, { SReg2, 0, 0 } },{"pop", 1, 0x0fa1, X, Cpu386|CpuNo64, wl_Suf|Seg3ShortForm|DefaultSize, { SReg3, 0, 0 } },/* In 64bit mode, the operand size is implicitly 64bit. */{"pop", 1, 0x58, X, Cpu64, wq_Suf|ShortForm|DefaultSize|NoRex64, { Reg16|Reg64, 0, 0 } },{"pop", 1, 0x8f, 0, Cpu64, wq_Suf|Modrm|DefaultSize|NoRex64, { Reg16|Reg64|WordMem, 0, 0 } },{"pop", 1, 0x0fa1, X, Cpu64, wq_Suf|Seg3ShortForm|DefaultSize|NoRex64, { SReg3, 0, 0 } },{"popa", 0, 0x61, X, Cpu186|CpuNo64, wl_Suf|DefaultSize, { 0, 0, 0 } },/* Exchange instructions. xchg commutes: we allow both operand orders. In the 64bit code, xchg eax, eax is reused for new nop instruction. */#if 0 /* While the two entries that are disabled generate shorter code for xchg eax, reg (on x86_64), the special case xchg eax, eax does not get handled correctly - it degenerates into nop, but that way the side effect of zero-extending eax to rax is lost. */{"xchg", 2, 0x90, X, 0, wlq_Suf|ShortForm, { WordReg, Acc, 0 } },{"xchg", 2, 0x90, X, 0, wlq_Suf|ShortForm, { Acc, WordReg, 0 } },#else{"xchg", 2, 0x90, X, CpuNo64, wl_Suf|ShortForm, { WordReg, Acc, 0 } },{"xchg", 2, 0x90, X, CpuNo64, wl_Suf|ShortForm, { Acc, WordReg, 0 } },{"xchg", 2, 0x90, X, Cpu64, wq_Suf|ShortForm, { Reg16|Reg64, Acc, 0 } },{"xchg", 2, 0x90, X, Cpu64, wq_Suf|ShortForm, { Acc, Reg16|Reg64, 0 } },#endif{"xchg", 2, 0x86, X, 0, bwlq_Suf|W|Modrm, { Reg, Reg|AnyMem, 0 } },{"xchg", 2, 0x86, X, 0, bwlq_Suf|W|Modrm, { Reg|AnyMem, Reg, 0 } },/* In/out from ports. *//* XXX should reject %rax */{"in", 2, 0xe4, X, 0, bwl_Suf|W, { Imm8, Acc, 0 } },{"in", 2, 0xec, X, 0, bwl_Suf|W, { InOutPortReg, Acc, 0 } },{"in", 1, 0xe4, X, 0, bwl_Suf|W, { Imm8, 0, 0 } },{"in", 1, 0xec, X, 0, bwl_Suf|W, { InOutPortReg, 0, 0 } },{"out", 2, 0xe6, X, 0, bwl_Suf|W, { Acc, Imm8, 0 } },{"out", 2, 0xee, X, 0, bwl_Suf|W, { Acc, InOutPortReg, 0 } },{"out", 1, 0xe6, X, 0, bwl_Suf|W, { Imm8, 0, 0 } },{"out", 1, 0xee, X, 0, bwl_Suf|W, { InOutPortReg, 0, 0 } },/* Load effective address. */{"lea", 2, 0x8d, X, 0, wlq_Suf|Modrm, { WordMem, WordReg, 0 } },/* Load segment registers from memory. */{"lds", 2, 0xc5, X, CpuNo64, wl_Suf|Modrm, { WordMem, WordReg, 0} },{"les", 2, 0xc4, X, CpuNo64, wl_Suf|Modrm, { WordMem, WordReg, 0} },{"lfs", 2, 0x0fb4, X, Cpu386, wl_Suf|Modrm, { WordMem, WordReg, 0} },{"lgs", 2, 0x0fb5, X, Cpu386, wl_Suf|Modrm, { WordMem, WordReg, 0} },{"lss", 2, 0x0fb2, X, Cpu386, wl_Suf|Modrm, { WordMem, WordReg, 0} },/* Flags register instructions. */{"clc", 0, 0xf8, X, 0, NoSuf, { 0, 0, 0} },{"cld", 0, 0xfc, X, 0, NoSuf, { 0, 0, 0} },{"cli", 0, 0xfa, X, 0, NoSuf, { 0, 0, 0} },{"clts", 0, 0x0f06, X, Cpu286, NoSuf, { 0, 0, 0} },{"cmc", 0, 0xf5, X, 0, NoSuf, { 0, 0, 0} },{"lahf", 0, 0x9f, X, CpuNo64,NoSuf, { 0, 0, 0} },{"sahf", 0, 0x9e, X, CpuNo64,NoSuf, { 0, 0, 0} },{"pushf", 0, 0x9c, X, CpuNo64,wl_Suf|DefaultSize, { 0, 0, 0} },{"pushf", 0, 0x9c, X, Cpu64, wq_Suf|DefaultSize|NoRex64,{ 0, 0, 0} },{"popf", 0, 0x9d, X, CpuNo64,wl_Suf|DefaultSize, { 0, 0, 0} },{"popf", 0, 0x9d, X, Cpu64, wq_Suf|DefaultSize|NoRex64,{ 0, 0, 0} },{"stc", 0, 0xf9, X, 0, NoSuf, { 0, 0, 0} },{"std", 0, 0xfd, X, 0, NoSuf, { 0, 0, 0} },{"sti", 0, 0xfb, X, 0, NoSuf, { 0, 0, 0} },
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -