PATCH: Remove InvMem from MMX/SSE instructions
H. J. Lu
hjl@lucon.org
Mon Jul 17 21:14:00 GMT 2006
On Mon, Jul 17, 2006 at 01:12:34PM -0700, H. J. Lu wrote:
> On Mon, Jul 17, 2006 at 06:18:58PM +0930, Alan Modra wrote:
> > On Sun, Jul 16, 2006 at 10:13:29AM -0700, H. J. Lu wrote:
> > > On Sun, Jul 16, 2006 at 01:23:56PM +0930, Alan Modra wrote:
> > > > On Thu, Jul 13, 2006 at 04:09:03PM -0700, H. J. Lu wrote:
> > > > > http://sourceware.org/ml/binutils/2001-05/msg00065.html
> > > > > http://sourceware.org/ml/binutils/2001-05/msg00187.html
> > > > >
> > > > > use InvMem on source operand to indicate that it must be register.
> > > > > I don't believe it is correct since RegYYY won't match memory anyway
> > > > > and InvMem is used to indicate how operand should be encoded. This
> > > > > patch removes it.
> > > >
> > > > It's true that the way the code is currently written that removing this
> > > > flag will not change the insn encoding. All InvMem does on *source*
> > > > operands of these reg->reg insns is document that the register is
> > > > encoded in the regmem field of the modrm byte. So why do you want to
> > > > remove documentation? There is certainly nothing wrong with InvMem on
> > > > these operands.
> > >
> > > Those operands only take registers and are encoded properly. What
> > > additional information does InvMem provide here?
> >
> > Didn't you read what I said? To a programmer reading i386.h, InvMem
> > says that this particular register operand is encoded in the regmem
> > field, and the other register is encoded in the reg field.
>
> InvMem is only checked on the destination register operand in
> instructions with 2 register operands. It looks like InvMem is really
> used on the destination register operand to indicate how to encode an
> instruction with 2 register operands.
>
This patch renames InvMem to RegMem and updates comments.
H.J.
----
gas/
2006-07-17 H.J. Lu <hongjiu.lu@intel.com>
* config/tc-i386.c (build_modrm_byte): Check RegMem instead of
AnyMem. Update comments.
* config/tc-i386.h (InvMem): Renamed to ...
(RegMem): This.
(AnyMem): Updated.
include/opcode/
2006-07-17 H.J. Lu <hongjiu.lu@intel.com>
* i386.h (i386_optab): Replace InvMem with RegMem. Remove
InvMem from sldt, smsw and str.
--- binutils/gas/config/tc-i386.c.invmem 2006-07-17 13:15:10.000000000 -0700
+++ binutils/gas/config/tc-i386.c 2006-07-17 13:57:28.000000000 -0700
@@ -3351,13 +3351,11 @@ build_modrm_byte ()
dest = source + 1;
i.rm.mode = 3;
- /* One of the register operands will be encoded in the i.tm.reg
- field, the other in the combined i.tm.mode and i.tm.regmem
- fields. If no form of this instruction supports a memory
- destination operand, then we assume the source operand may
- sometimes be a memory operand and so we need to store the
+ /* The register destination operand will be encoded in the
+ i.rm.reg field or in the combined i.rm.mode and i.rm.regmem
+ fields. If its RegMem bit is 0, we need to store the
destination in the i.rm.reg field. */
- if ((i.tm.operand_types[dest] & AnyMem) == 0)
+ if ((i.tm.operand_types[dest] & RegMem) == 0)
{
i.rm.reg = i.op[dest].regs->reg_num;
i.rm.regmem = i.op[source].regs->reg_num;
--- binutils/gas/config/tc-i386.h.invmem 2006-07-17 13:15:10.000000000 -0700
+++ binutils/gas/config/tc-i386.h 2006-07-17 13:43:49.000000000 -0700
@@ -285,12 +285,12 @@ typedef struct
#define RegXMM 0x20000000 /* XMM registers in PIII */
#define EsSeg 0x40000000 /* String insn operand with fixed es segment */
- /* InvMem is for instructions with a modrm byte that only allow a
- general register encoding in the i.tm.mode and i.tm.regmem fields,
- eg. control reg moves. They really ought to support a memory form,
- but don't, so we add an InvMem flag to the register operand to
- indicate that it should be encoded in the i.tm.regmem field. */
-#define InvMem 0x80000000
+ /* For instructions with 2 register operands, the destination operand
+ can be encoded in either the i.rm.reg field or the i.rm.mode and
+ i.rm.regmem fields. We add a RegMem flag to the destination
+ operand to indicate that it should be encoded in the i.rm.regmem
+ field. */
+#define RegMem 0x80000000
#define Reg (Reg8|Reg16|Reg32|Reg64) /* gen'l register */
#define WordReg (Reg16|Reg32|Reg64)
@@ -298,7 +298,9 @@ typedef struct
#define Imm (Imm8|Imm8S|Imm16|Imm32S|Imm32|Imm64) /* gen'l immediate */
#define EncImm (Imm8|Imm16|Imm32|Imm32S) /* Encodable gen'l immediate */
#define Disp (Disp8|Disp16|Disp32|Disp32S|Disp64) /* General displacement */
-#define AnyMem (Disp8|Disp16|Disp32|Disp32S|BaseIndex|InvMem) /* General memory */
+/* FIXME: We add RegMem to AnyMem. But it only applies to the register
+ destination operand in instructions with 2 register operands. */
+#define AnyMem (Disp8|Disp16|Disp32|Disp32S|BaseIndex|RegMem) /* General memory */
/* The following aliases are defined because the opcode table
carefully specifies the allowed memory types for each instruction.
At the moment we can only tell a memory reference size by the
--- binutils/include/opcode/i386.h.invmem 2006-07-14 09:39:20.000000000 -0700
+++ binutils/include/opcode/i386.h 2006-07-17 13:45:01.000000000 -0700
@@ -98,9 +98,9 @@ static const template i386_optab[] =
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|InvMem, 0 } },
+{ "mov", 2, 0x8c, X, 0, wl_Suf|Modrm, { SReg2, WordReg|RegMem, 0 } },
{ "mov", 2, 0x8c, X, 0, w_Suf|Modrm|IgnoreSize, { SReg2, WordMem, 0 } },
-{ "mov", 2, 0x8c, X, Cpu386, wl_Suf|Modrm, { SReg3, WordReg|InvMem, 0 } },
+{ "mov", 2, 0x8c, X, Cpu386, wl_Suf|Modrm, { SReg3, WordReg|RegMem, 0 } },
{ "mov", 2, 0x8c, X, Cpu386, w_Suf|Modrm|IgnoreSize, { SReg3, WordMem, 0 } },
{ "mov", 2, 0x8e, X, 0, wl_Suf|Modrm|IgnoreSize, { WordReg, SReg2, 0 } },
{ "mov", 2, 0x8e, X, 0, w_Suf|Modrm|IgnoreSize, { WordMem, SReg2, 0 } },
@@ -108,11 +108,11 @@ static const template i386_optab[] =
{ "mov", 2, 0x8e, X, Cpu386, w_Suf|Modrm|IgnoreSize, { 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|CpuNo64, l_Suf|D|Modrm|IgnoreSize, { Test, Reg32|InvMem, 0} },
+{ "mov", 2, 0x0f20, X, Cpu386|CpuNo64, l_Suf|D|Modrm|IgnoreSize,{ Control, Reg32|RegMem, 0} },
+{ "mov", 2, 0x0f20, X, Cpu64, q_Suf|D|Modrm|IgnoreSize|NoRex64,{ Control, Reg64|RegMem, 0} },
+{ "mov", 2, 0x0f21, X, Cpu386|CpuNo64, l_Suf|D|Modrm|IgnoreSize,{ Debug, Reg32|RegMem, 0} },
+{ "mov", 2, 0x0f21, X, Cpu64, q_Suf|D|Modrm|IgnoreSize|NoRex64,{ Debug, Reg64|RegMem, 0} },
+{ "mov", 2, 0x0f24, X, Cpu386|CpuNo64, l_Suf|D|Modrm|IgnoreSize, { Test, Reg32|RegMem, 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 } },
@@ -578,11 +578,11 @@ static const template i386_optab[] =
{"sgdt", 1, 0x0f01, 0, Cpu64, q_Suf|Modrm|NoRex64, { LLongMem, 0, 0} },
{"sidt", 1, 0x0f01, 1, Cpu286|CpuNo64, wl_Suf|Modrm, { WordMem, 0, 0} },
{"sidt", 1, 0x0f01, 1, Cpu64, q_Suf|Modrm|NoRex64, { LLongMem, 0, 0} },
-{"sldt", 1, 0x0f00, 0, Cpu286, wlq_Suf|Modrm, { WordReg|InvMem, 0, 0} },
+{"sldt", 1, 0x0f00, 0, Cpu286, wlq_Suf|Modrm, { WordReg, 0, 0} },
{"sldt", 1, 0x0f00, 0, Cpu286, w_Suf|Modrm|IgnoreSize,{ ShortMem, 0, 0} },
-{"smsw", 1, 0x0f01, 4, Cpu286, wlq_Suf|Modrm, { WordReg|InvMem, 0, 0} },
+{"smsw", 1, 0x0f01, 4, Cpu286, wlq_Suf|Modrm, { WordReg, 0, 0} },
{"smsw", 1, 0x0f01, 4, Cpu286, w_Suf|Modrm|IgnoreSize,{ ShortMem, 0, 0} },
-{"str", 1, 0x0f00, 1, Cpu286, wlq_Suf|Modrm, { WordReg|InvMem, 0, 0} },
+{"str", 1, 0x0f00, 1, Cpu286, wlq_Suf|Modrm, { WordReg, 0, 0} },
{"str", 1, 0x0f00, 1, Cpu286, w_Suf|Modrm|IgnoreSize,{ ShortMem, 0, 0} },
{"verr", 1, 0x0f00, 4, Cpu286, w_Suf|Modrm|IgnoreSize,{ Reg16|ShortMem, 0, 0} },
@@ -1017,12 +1017,12 @@ static const template i386_optab[] =
{"movq", 2, 0xb0, X, Cpu64, NoSuf|W|ShortForm|Size64,{ Imm64, Reg64, 0 } },
/* The segment register moves accept Reg64 so that a segment register
can be copied to a 64 bit register, and vice versa. */
-{"movq", 2, 0x8c, X, Cpu64, NoSuf|Modrm|Size64, { SReg2|SReg3, Reg64|InvMem, 0 } },
+{"movq", 2, 0x8c, X, Cpu64, NoSuf|Modrm|Size64, { SReg2|SReg3, Reg64|RegMem, 0 } },
{"movq", 2, 0x8e, X, Cpu64, NoSuf|Modrm|Size64, { Reg64, SReg2|SReg3, 0 } },
/* Move to/from control debug registers. In the 16 or 32bit modes they are 32bit. In the 64bit
mode they are 64bit.*/
-{"movq", 2, 0x0f20, X, Cpu64, NoSuf|D|Modrm|IgnoreSize|NoRex64|Size64,{ Control, Reg64|InvMem, 0} },
-{"movq", 2, 0x0f21, X, Cpu64, NoSuf|D|Modrm|IgnoreSize|NoRex64|Size64,{ Debug, Reg64|InvMem, 0} },
+{"movq", 2, 0x0f20, X, Cpu64, NoSuf|D|Modrm|IgnoreSize|NoRex64|Size64,{ Control, Reg64|RegMem, 0} },
+{"movq", 2, 0x0f21, X, Cpu64, NoSuf|D|Modrm|IgnoreSize|NoRex64|Size64,{ Debug, Reg64|RegMem, 0} },
/* Real MMX instructions. */
{"packssdw", 2, 0x0f6b, X, CpuMMX, NoSuf|IgnoreSize|Modrm, { RegMMX|LongMem, RegMMX, 0 } },
{"packssdw", 2, 0x660f6b,X,CpuSSE2,NoSuf|IgnoreSize|Modrm, { RegXMM|LLongMem, RegXMM, 0 } },
More information about the Binutils
mailing list