PATCH: PR gas/1874: mwait/monitor don't work in 64bit

classic Classic list List threaded Threaded
19 messages Options
Reply | Threaded
Open this post in threaded view
|

PATCH: PR gas/1874: mwait/monitor don't work in 64bit

H.J. Lu-27
This patch adds 64bit support to mwait/monitor.


H.J.
----
gas/testsuite/

2005-11-15  H.J. Lu  <[hidden email]>

        PR gas/1874
        * gas/i386/i386.exp: Add x86-64-prescott for 64bit.

        * gas/i386/x86-64-prescott.d: New file.
        * gas/i386/x86-64-prescott.s: Likewise.

include/opcode/

2005-11-15  H.J. Lu  <[hidden email]>

        PR gas/1874
        * i386.h (i386_optab): Add 64bit support to monitor and
        mwait.

opcodes/

2005-11-15  H.J. Lu  <[hidden email]>

        PR gas/1874
        * i386-dis.c (PNI_Fixup): Add 64bit support to monitor and
        mwait.

--- binutils/gas/testsuite/gas/i386/i386.exp.pni 2005-11-11 10:48:53.000000000 -0800
+++ binutils/gas/testsuite/gas/i386/i386.exp 2005-11-15 15:37:50.000000000 -0800
@@ -131,6 +131,7 @@ if [expr ([istarget "i*86-*-*"] || [ista
     run_dump_test "svme64"
     run_dump_test "x86-64-vmx"
     run_dump_test "immed64"
+    run_dump_test "x86-64-prescott"
 
     # For ELF targets verify that @unwind works.
     if { ([istarget "*-*-elf*"] || [istarget "*-*-linux*"]
--- binutils/gas/testsuite/gas/i386/x86-64-prescott.d.pni 2005-11-15 15:33:49.000000000 -0800
+++ binutils/gas/testsuite/gas/i386/x86-64-prescott.d 2005-11-15 15:48:22.000000000 -0800
@@ -0,0 +1,36 @@
+#objdump: -dw
+#name: x86-64 prescott
+
+.*: +file format .*
+
+Disassembly of section .text:
+
+0+000 <foo>:
+   0: 66 0f d0 01 [ ]*addsubpd \(%rcx\),%xmm0
+   4: 66 0f d0 ca [ ]*addsubpd %xmm2,%xmm1
+   8: f2 0f d0 13 [ ]*addsubps \(%rbx\),%xmm2
+   c: f2 0f d0 dc [ ]*addsubps %xmm4,%xmm3
+  10: df 88 90 90 90 90 [ ]*fisttp 0xffffffff90909090\(%rax\)
+  16: db 88 90 90 90 90 [ ]*fisttpl 0xffffffff90909090\(%rax\)
+  1c: dd 88 90 90 90 90 [ ]*fisttpll 0xffffffff90909090\(%rax\)
+  22: 66 0f 7c 65 00 [ ]*haddpd 0x0\(%rbp\),%xmm4
+  27: 66 0f 7c ee [ ]*haddpd %xmm6,%xmm5
+  2b: f2 0f 7c 37 [ ]*haddps \(%rdi\),%xmm6
+  2f: f2 0f 7c f8 [ ]*haddps %xmm0,%xmm7
+  33: 66 0f 7d c1 [ ]*hsubpd %xmm1,%xmm0
+  37: 66 0f 7d 0a [ ]*hsubpd \(%rdx\),%xmm1
+  3b: f2 0f 7d d2 [ ]*hsubps %xmm2,%xmm2
+  3f: f2 0f 7d 1c 24 [ ]*hsubps \(%rsp\),%xmm3
+  44: f2 0f f0 2e [ ]*lddqu  \(%rsi\),%xmm5
+  48: 0f 01 c8 [ ]*monitor %rax,%rcx,%rdx
+  4b: 0f 01 c8 [ ]*monitor %rax,%rcx,%rdx
+  4e: f2 0f 12 f7 [ ]*movddup %xmm7,%xmm6
+  52: f2 0f 12 38 [ ]*movddup \(%rax\),%xmm7
+  56: f3 0f 16 01 [ ]*movshdup \(%rcx\),%xmm0
+  5a: f3 0f 16 ca [ ]*movshdup %xmm2,%xmm1
+  5e: f3 0f 12 13 [ ]*movsldup \(%rbx\),%xmm2
+  62: f3 0f 12 dc [ ]*movsldup %xmm4,%xmm3
+  66: 0f 01 c9 [ ]*mwait  %rax,%rcx
+  69: 0f 01 c9 [ ]*mwait  %rax,%rcx
+  6c: 00 00 [ ]*add    %al,\(%rax\)
+ ...
--- binutils/gas/testsuite/gas/i386/x86-64-prescott.s.pni 2005-11-15 15:33:47.000000000 -0800
+++ binutils/gas/testsuite/gas/i386/x86-64-prescott.s 2005-11-15 15:32:38.000000000 -0800
@@ -0,0 +1,32 @@
+#Prescott New Instructions
+
+ .text
+foo:
+ addsubpd (%rcx),%xmm0
+ addsubpd %xmm2,%xmm1
+ addsubps (%rbx),%xmm2
+ addsubps %xmm4,%xmm3
+ fisttp 0x90909090(%rax)
+ fisttpl 0x90909090(%rax)
+ fisttpll 0x90909090(%rax)
+ haddpd 0x0(%rbp),%xmm4
+ haddpd %xmm6,%xmm5
+ haddps (%rdi),%xmm6
+ haddps %xmm0,%xmm7
+ hsubpd %xmm1,%xmm0
+ hsubpd (%rdx),%xmm1
+ hsubps %xmm2,%xmm2
+ hsubps (%rsp,1),%xmm3
+ lddqu (%rsi),%xmm5
+ monitor
+ monitor %rax,%rcx,%rdx
+ movddup %xmm7,%xmm6
+ movddup (%rax),%xmm7
+ movshdup (%rcx),%xmm0
+ movshdup %xmm2,%xmm1
+ movsldup (%rbx),%xmm2
+ movsldup %xmm4,%xmm3
+ mwait
+ mwait %rax,%rcx
+
+ .p2align 4,0
--- binutils/include/opcode/i386.h.pni 2005-07-27 08:41:15.000000000 -0700
+++ binutils/include/opcode/i386.h 2005-11-15 15:56:08.000000000 -0800
@@ -1347,13 +1347,17 @@ static const template i386_optab[] =
 {"lddqu",     2, 0xf20ff0,  X, CpuPNI, NoSuf|IgnoreSize|Modrm, { LLongMem, RegXMM, 0 } },
 {"monitor",   0, 0x0f01, 0xc8, CpuPNI, NoSuf|ImmExt, { 0, 0, 0} },
 /* Need to ensure only "monitor %eax,%ecx,%edx" is accepted. */
-{"monitor",   3, 0x0f01, 0xc8, CpuPNI, NoSuf|ImmExt, { Reg32, Reg32, Reg32} },
+{"monitor",   3, 0x0f01, 0xc8, CpuPNI|CpuNo64, NoSuf|ImmExt, { Reg32, Reg32, Reg32 } },
+/* Need to ensure only "monitor %rax,%rcx,%rdx" is accepted. */
+{"monitor",   3, 0x0f01, 0xc8, CpuPNI|Cpu64, NoSuf|ImmExt|NoRex64, { Reg64, Reg64, Reg64 } },
 {"movddup",   2, 0xf20f12,  X, CpuPNI, NoSuf|IgnoreSize|Modrm, { RegXMM|LLongMem, RegXMM, 0 } },
 {"movshdup",  2, 0xf30f16,  X, CpuPNI, NoSuf|IgnoreSize|Modrm, { RegXMM|LLongMem, RegXMM, 0 } },
 {"movsldup",  2, 0xf30f12,  X, CpuPNI, NoSuf|IgnoreSize|Modrm, { RegXMM|LLongMem, RegXMM, 0 } },
 {"mwait",     0, 0x0f01, 0xc9, CpuPNI, NoSuf|ImmExt, { 0, 0, 0} },
 /* Need to ensure only "mwait %eax,%ecx" is accepted.  */
-{"mwait",     2, 0x0f01, 0xc9, CpuPNI, NoSuf|ImmExt, { Reg32, Reg32, 0} },
+{"mwait",     2, 0x0f01, 0xc9, CpuPNI|CpuNo64, NoSuf|ImmExt, { Reg32, Reg32, 0} },
+/* Need to ensure only "mwait %rax,%rcx" is accepted.  */
+{"mwait",     2, 0x0f01, 0xc9, CpuPNI|Cpu64, NoSuf|ImmExt|NoRex64, { Reg64, Reg64, 0 } },
 
 /* VMX instructions.  */
 {"vmcall",    0, 0x0f01, 0xc1, CpuVMX, NoSuf|ImmExt, { 0, 0, 0} },
--- binutils/opcodes/i386-dis.c.pni 2005-11-11 10:48:50.000000000 -0800
+++ binutils/opcodes/i386-dis.c 2005-11-15 15:50:30.000000000 -0800
@@ -4423,7 +4423,12 @@ PNI_Fixup (int extrachar ATTRIBUTE_UNUSE
   /* mwait %eax,%ecx  */
   strcpy (p, "mwait");
   if (!intel_syntax)
-    strcpy (op1out, names32[0]);
+    {
+      if (!mode_64bit)
+ strcpy (op1out, names32[0]);
+      else
+ strcpy (op1out, names64[0]);
+    }
  }
       else
  {
@@ -4440,12 +4445,18 @@ PNI_Fixup (int extrachar ATTRIBUTE_UNUSE
   strcpy (op1out, names32[0]);
   used_prefixes |= PREFIX_ADDR;
  }
-      strcpy (op3out, names32[2]);
+      if (!mode_64bit)
+ strcpy (op3out, names32[2]);
+      else
+ strcpy (op3out, names64[2]);
     }
  }
       if (!intel_syntax)
  {
-  strcpy (op2out, names32[1]);
+  if (!mode_64bit)
+    strcpy (op2out, names32[1]);
+  else
+    strcpy (op2out, names64[1]);
   two_source_ops = 1;
  }
 
Reply | Threaded
Open this post in threaded view
|

Re: PATCH: PR gas/1874: mwait/monitor don't work in 64bit

H.J. Lu-27
On Tue, Nov 15, 2005 at 04:08:18PM -0800, H. J. Lu wrote:
> This patch adds 64bit support to mwait/monitor.
>
>

I checked icc. We only need 64bit monitor with 64bit address. Here is
the updated patch.


H.J.
---
gas/testsuite/

2005-11-15  H.J. Lu  <[hidden email]>

        PR gas/1874
        * gas/i386/i386.exp: Add x86-64-prescott for 64bit.

        * gas/i386/x86-64-prescott.d: New file.
        * gas/i386/x86-64-prescott.s: Likewise.

include/opcode/

2005-11-15  H.J. Lu  <[hidden email]>

        PR gas/1874
        * i386.h (i386_optab): Add 64bit monitor.

--- binutils/gas/testsuite/gas/i386/i386.exp.pni 2005-11-11 10:48:53.000000000 -0800
+++ binutils/gas/testsuite/gas/i386/i386.exp 2005-11-15 15:37:50.000000000 -0800
@@ -131,6 +131,7 @@ if [expr ([istarget "i*86-*-*"] || [ista
     run_dump_test "svme64"
     run_dump_test "x86-64-vmx"
     run_dump_test "immed64"
+    run_dump_test "x86-64-prescott"
 
     # For ELF targets verify that @unwind works.
     if { ([istarget "*-*-elf*"] || [istarget "*-*-linux*"]
--- binutils/gas/testsuite/gas/i386/x86-64-prescott.d.pni 2005-11-15 15:33:49.000000000 -0800
+++ binutils/gas/testsuite/gas/i386/x86-64-prescott.d 2005-11-15 23:29:48.000000000 -0800
@@ -0,0 +1,36 @@
+#objdump: -dw
+#name: x86-64 prescott
+
+.*: +file format .*
+
+Disassembly of section .text:
+
+0+000 <foo>:
+   0: 66 0f d0 01 [ ]*addsubpd \(%rcx\),%xmm0
+   4: 66 0f d0 ca [ ]*addsubpd %xmm2,%xmm1
+   8: f2 0f d0 13 [ ]*addsubps \(%rbx\),%xmm2
+   c: f2 0f d0 dc [ ]*addsubps %xmm4,%xmm3
+  10: df 88 90 90 90 90 [ ]*fisttp 0xffffffff90909090\(%rax\)
+  16: db 88 90 90 90 90 [ ]*fisttpl 0xffffffff90909090\(%rax\)
+  1c: dd 88 90 90 90 90 [ ]*fisttpll 0xffffffff90909090\(%rax\)
+  22: 66 0f 7c 65 00 [ ]*haddpd 0x0\(%rbp\),%xmm4
+  27: 66 0f 7c ee [ ]*haddpd %xmm6,%xmm5
+  2b: f2 0f 7c 37 [ ]*haddps \(%rdi\),%xmm6
+  2f: f2 0f 7c f8 [ ]*haddps %xmm0,%xmm7
+  33: 66 0f 7d c1 [ ]*hsubpd %xmm1,%xmm0
+  37: 66 0f 7d 0a [ ]*hsubpd \(%rdx\),%xmm1
+  3b: f2 0f 7d d2 [ ]*hsubps %xmm2,%xmm2
+  3f: f2 0f 7d 1c 24 [ ]*hsubps \(%rsp\),%xmm3
+  44: f2 0f f0 2e [ ]*lddqu  \(%rsi\),%xmm5
+  48: 0f 01 c8 [ ]*monitor %rax,%ecx,%edx
+  4b: 0f 01 c8 [ ]*monitor %rax,%ecx,%edx
+  4e: f2 0f 12 f7 [ ]*movddup %xmm7,%xmm6
+  52: f2 0f 12 38 [ ]*movddup \(%rax\),%xmm7
+  56: f3 0f 16 01 [ ]*movshdup \(%rcx\),%xmm0
+  5a: f3 0f 16 ca [ ]*movshdup %xmm2,%xmm1
+  5e: f3 0f 12 13 [ ]*movsldup \(%rbx\),%xmm2
+  62: f3 0f 12 dc [ ]*movsldup %xmm4,%xmm3
+  66: 0f 01 c9 [ ]*mwait  %eax,%ecx
+  69: 0f 01 c9 [ ]*mwait  %eax,%ecx
+  6c: 00 00 [ ]*add    %al,\(%rax\)
+ ...
--- binutils/gas/testsuite/gas/i386/x86-64-prescott.s.pni 2005-11-15 15:33:47.000000000 -0800
+++ binutils/gas/testsuite/gas/i386/x86-64-prescott.s 2005-11-15 23:29:39.000000000 -0800
@@ -0,0 +1,32 @@
+#Prescott New Instructions
+
+ .text
+foo:
+ addsubpd (%rcx),%xmm0
+ addsubpd %xmm2,%xmm1
+ addsubps (%rbx),%xmm2
+ addsubps %xmm4,%xmm3
+ fisttp 0x90909090(%rax)
+ fisttpl 0x90909090(%rax)
+ fisttpll 0x90909090(%rax)
+ haddpd 0x0(%rbp),%xmm4
+ haddpd %xmm6,%xmm5
+ haddps (%rdi),%xmm6
+ haddps %xmm0,%xmm7
+ hsubpd %xmm1,%xmm0
+ hsubpd (%rdx),%xmm1
+ hsubps %xmm2,%xmm2
+ hsubps (%rsp,1),%xmm3
+ lddqu (%rsi),%xmm5
+ monitor
+ monitor %rax,%ecx,%edx
+ movddup %xmm7,%xmm6
+ movddup (%rax),%xmm7
+ movshdup (%rcx),%xmm0
+ movshdup %xmm2,%xmm1
+ movsldup (%rbx),%xmm2
+ movsldup %xmm4,%xmm3
+ mwait
+ mwait %eax,%ecx
+
+ .p2align 4,0
--- binutils/include/opcode/i386.h.pni 2005-07-27 08:41:15.000000000 -0700
+++ binutils/include/opcode/i386.h 2005-11-15 22:38:57.000000000 -0800
@@ -1347,7 +1347,9 @@ static const template i386_optab[] =
 {"lddqu",     2, 0xf20ff0,  X, CpuPNI, NoSuf|IgnoreSize|Modrm, { LLongMem, RegXMM, 0 } },
 {"monitor",   0, 0x0f01, 0xc8, CpuPNI, NoSuf|ImmExt, { 0, 0, 0} },
 /* Need to ensure only "monitor %eax,%ecx,%edx" is accepted. */
-{"monitor",   3, 0x0f01, 0xc8, CpuPNI, NoSuf|ImmExt, { Reg32, Reg32, Reg32} },
+{"monitor",   3, 0x0f01, 0xc8, CpuPNI|CpuNo64, NoSuf|ImmExt, { Reg32, Reg32, Reg32 } },
+/* Need to ensure only "monitor %rax,%ecx,%edx" is accepted. */
+{"monitor",   3, 0x0f01, 0xc8, CpuPNI|Cpu64, NoSuf|ImmExt|NoRex64, { Reg64, Reg32, Reg32 } },
 {"movddup",   2, 0xf20f12,  X, CpuPNI, NoSuf|IgnoreSize|Modrm, { RegXMM|LLongMem, RegXMM, 0 } },
 {"movshdup",  2, 0xf30f16,  X, CpuPNI, NoSuf|IgnoreSize|Modrm, { RegXMM|LLongMem, RegXMM, 0 } },
 {"movsldup",  2, 0xf30f12,  X, CpuPNI, NoSuf|IgnoreSize|Modrm, { RegXMM|LLongMem, RegXMM, 0 } },
Reply | Threaded
Open this post in threaded view
|

Re: PATCH: PR gas/1874: mwait/monitor don't work in 64bit

Jan Beulich
>-{"monitor",   3, 0x0f01, 0xc8, CpuPNI, NoSuf|ImmExt, { Reg32, Reg32,
Reg32} },
>+{"monitor",   3, 0x0f01, 0xc8, CpuPNI|CpuNo64, NoSuf|ImmExt, { Reg32,
Reg32, Reg32 } },
>+/* Need to ensure only "monitor %rax,%ecx,%edx" is accepted. */
>+{"monitor",   3, 0x0f01, 0xc8, CpuPNI|Cpu64,
NoSuf|ImmExt|NoRex64, { Reg64, Reg32, Reg32 } },

I'm afraid this isn't correct. While it took your Premier Support folks
several months to come up with an obviously wrong answer (experiments
show that the first operand's size is determined by the address size in
effect), they still didn't manage to get me a correct answer. However,
as already said, the operand size is controlled by the address size (and
thus without prefixes, and hence implicitly also without operands)
everything is correct, the 32-bit first-operand-form is still valid (and
thus shouldn't be disallowed).

When I did these experiments, the mere fact that expressing this in
gas'/opcodes' terms isn't obvious (and I didn't have a lot of time to
spend on this) kept me from submitting a patch to obtain correct (that
is, matching reality short of having a proper specification) behavior.

Jan
Reply | Threaded
Open this post in threaded view
|

Re: PATCH: PR gas/1874: mwait/monitor don't work in 64bit

H.J. Lu-27
On Wed, Nov 16, 2005 at 05:12:24PM +0100, Jan Beulich wrote:

> >-{"monitor",   3, 0x0f01, 0xc8, CpuPNI, NoSuf|ImmExt, { Reg32, Reg32,
> Reg32} },
> >+{"monitor",   3, 0x0f01, 0xc8, CpuPNI|CpuNo64, NoSuf|ImmExt, { Reg32,
> Reg32, Reg32 } },
> >+/* Need to ensure only "monitor %rax,%ecx,%edx" is accepted. */
> >+{"monitor",   3, 0x0f01, 0xc8, CpuPNI|Cpu64,
> NoSuf|ImmExt|NoRex64, { Reg64, Reg32, Reg32 } },
>
> I'm afraid this isn't correct. While it took your Premier Support folks
> several months to come up with an obviously wrong answer (experiments
> show that the first operand's size is determined by the address size in
> effect), they still didn't manage to get me a correct answer. However,

I will try to get the correct answer this time :-).

> as already said, the operand size is controlled by the address size (and
> thus without prefixes, and hence implicitly also without operands)
> everything is correct, the 32-bit first-operand-form is still valid (and
> thus shouldn't be disallowed).
>

Are you saying "monitor %eax,%ecx,%edx" should be allowed in 64bit
mode? Why? How will it be used?


H.J.
Reply | Threaded
Open this post in threaded view
|

Re: PATCH: PR gas/1874: mwait/monitor don't work in 64bit

Jan Beulich
>Are you saying "monitor %eax,%ecx,%edx" should be allowed in 64bit
>mode? Why? How will it be used?

Just like any other 32-bit addressing in 64-bit mode: probably rarely,
but it should be allowed for whoever is able to find meaningful use for
this. We also don't disallow 16-bit addressing in 32-bit mode, even
though it's unlikely to ever be used...

Jan
Reply | Threaded
Open this post in threaded view
|

Re: PATCH: PR gas/1874: mwait/monitor don't work in 64bit

H.J. Lu-27
On Wed, Nov 16, 2005 at 06:12:30PM +0100, Jan Beulich wrote:
> >Are you saying "monitor %eax,%ecx,%edx" should be allowed in 64bit
> >mode? Why? How will it be used?
>
> Just like any other 32-bit addressing in 64-bit mode: probably rarely,
> but it should be allowed for whoever is able to find meaningful use for
> this. We also don't disallow 16-bit addressing in 32-bit mode, even
> though it's unlikely to ever be used...

I disagree. In 64bit mode, the correct way to use monitor is

        load %rax
        load %edx
        load %ecx
        monitor %rax, %edx, %ecx # It is the same as "monitor".

It is misleading and confusing to do

        load %eax
        load %edx
        load %ecx
        monitor %eax, %edx, %ecx

Assembler will generate the same opcode for those forms anyway. I don't
see why "monitor %eax, %edx, %ecx" has to be allowed in 64bit.


H.J.
Reply | Threaded
Open this post in threaded view
|

Re: PATCH: PR gas/1874: mwait/monitor don't work in 64bit

Jan Beulich
>>> "H. J. Lu" <[hidden email]> 16.11.05 18:19:21 >>>
>On Wed, Nov 16, 2005 at 06:12:30PM +0100, Jan Beulich wrote:
>> >Are you saying "monitor %eax,%ecx,%edx" should be allowed in 64bit
>> >mode? Why? How will it be used?
>>
>> Just like any other 32-bit addressing in 64-bit mode: probably
rarely,
>> but it should be allowed for whoever is able to find meaningful use
for

>> this. We also don't disallow 16-bit addressing in 32-bit mode, even
>> though it's unlikely to ever be used...
>
>I disagree. In 64bit mode, the correct way to use monitor is
>
> load %rax
> load %edx
> load %ecx
> monitor %rax, %edx, %ecx # It is the same as "monitor".
>
>It is misleading and confusing to do
>
> load %eax
> load %edx
> load %ecx
> monitor %eax, %edx, %ecx
>
>Assembler will generate the same opcode for those forms anyway. I
don't
>see why "monitor %eax, %edx, %ecx" has to be allowed in 64bit.

That's what's wrong - the second form should emit an address size
override.

Jan
Reply | Threaded
Open this post in threaded view
|

Re: PATCH: PR gas/1874: mwait/monitor don't work in 64bit

H.J. Lu-27
On Wed, Nov 16, 2005 at 06:31:27PM +0100, Jan Beulich wrote:

> >>> "H. J. Lu" <[hidden email]> 16.11.05 18:19:21 >>>
> >On Wed, Nov 16, 2005 at 06:12:30PM +0100, Jan Beulich wrote:
> >> >Are you saying "monitor %eax,%ecx,%edx" should be allowed in 64bit
> >> >mode? Why? How will it be used?
> >>
> >> Just like any other 32-bit addressing in 64-bit mode: probably
> rarely,
> >> but it should be allowed for whoever is able to find meaningful use
> for
> >> this. We also don't disallow 16-bit addressing in 32-bit mode, even
> >> though it's unlikely to ever be used...
> >
> >I disagree. In 64bit mode, the correct way to use monitor is
> >
> > load %rax
> > load %edx
> > load %ecx
> > monitor %rax, %edx, %ecx # It is the same as "monitor".
> >
> >It is misleading and confusing to do
> >
> > load %eax
> > load %edx
> > load %ecx
> > monitor %eax, %edx, %ecx
> >
> >Assembler will generate the same opcode for those forms anyway. I
> don't
> >see why "monitor %eax, %edx, %ecx" has to be allowed in 64bit.
>
> That's what's wrong - the second form should emit an address size
> override.

I am trying to find out if the address size prefix will be ignored or
not.


H.J.
Reply | Threaded
Open this post in threaded view
|

Re: PATCH: PR gas/1874: mwait/monitor don't work in 64bit

H.J. Lu-27
On Wed, Nov 16, 2005 at 09:39:34AM -0800, H. J. Lu wrote:

> On Wed, Nov 16, 2005 at 06:31:27PM +0100, Jan Beulich wrote:
> > >>> "H. J. Lu" <[hidden email]> 16.11.05 18:19:21 >>>
> > >On Wed, Nov 16, 2005 at 06:12:30PM +0100, Jan Beulich wrote:
> > >> >Are you saying "monitor %eax,%ecx,%edx" should be allowed in 64bit
> > >> >mode? Why? How will it be used?
> > >>
> > >> Just like any other 32-bit addressing in 64-bit mode: probably
> > rarely,
> > >> but it should be allowed for whoever is able to find meaningful use
> > for
> > >> this. We also don't disallow 16-bit addressing in 32-bit mode, even
> > >> though it's unlikely to ever be used...
> > >
> > >I disagree. In 64bit mode, the correct way to use monitor is
> > >
> > > load %rax
> > > load %edx
> > > load %ecx
> > > monitor %rax, %edx, %ecx # It is the same as "monitor".
> > >
> > >It is misleading and confusing to do
> > >
> > > load %eax
> > > load %edx
> > > load %ecx
> > > monitor %eax, %edx, %ecx
> > >
> > >Assembler will generate the same opcode for those forms anyway. I
> > don't
> > >see why "monitor %eax, %edx, %ecx" has to be allowed in 64bit.
> >
> > That's what's wrong - the second form should emit an address size
> > override.
>
> I am trying to find out if the address size prefix will be ignored or
> not.
>

Here is the information I got from our chip people. The address size
override prefix is honored for "monitor" in both 16 and 32bit modes.
In 64bit mode, RCX and RDX are used for "monitor", RAX and RCX are
used for "mwait". This patch implements it.


----
gas/testsuite/

2005-11-16  H.J. Lu  <[hidden email]>

        PR gas/1874
        * gas/i386/i386.exp: Add x86-64-prescott for 64bit.

        * gas/i386/prescott.s: Test address size override for monitor.
        * gas/i386/prescott.d: Updated.

        * gas/i386/x86-64-prescott.d: New file.
        * gas/i386/x86-64-prescott.s: Likewise.

include/opcode/

2005-11-16  H.J. Lu  <[hidden email]>

        PR gas/1874
        * i386.h (i386_optab): Add 64bit support for monitor and
        mwait. Add address size override support for monitor.

opcodes/

2005-11-16  H.J. Lu  <[hidden email]>

        PR gas/1874
        * i386-dis.c (PNI_Fixup): Add 64bit and address size override
        support for monitor and mwait.

--- binutils/gas/testsuite/gas/i386/i386.exp.pni 2005-11-11 10:48:53.000000000 -0800
+++ binutils/gas/testsuite/gas/i386/i386.exp 2005-11-15 15:37:50.000000000 -0800
@@ -131,6 +131,7 @@ if [expr ([istarget "i*86-*-*"] || [ista
     run_dump_test "svme64"
     run_dump_test "x86-64-vmx"
     run_dump_test "immed64"
+    run_dump_test "x86-64-prescott"
 
     # For ELF targets verify that @unwind works.
     if { ([istarget "*-*-elf*"] || [istarget "*-*-linux*"]
--- binutils/gas/testsuite/gas/i386/prescott.d.pni 2004-06-23 08:06:57.000000000 -0700
+++ binutils/gas/testsuite/gas/i386/prescott.d 2005-11-16 11:00:18.000000000 -0800
@@ -32,5 +32,6 @@ Disassembly of section .text:
   62: f3 0f 12 dc [ ]*movsldup %xmm4,%xmm3
   66: 0f 01 c9 [ ]*mwait  %eax,%ecx
   69: 0f 01 c9 [ ]*mwait  %eax,%ecx
-  6c: 00 00 [ ]*add    %al,\(%eax\)
+  6c: 67 0f 01 c8 [ ]*addr16 monitor %ax,%ecx,%edx
+  70: 67 0f 01 c8 [ ]*addr16 monitor %ax,%ecx,%edx
  ...
--- binutils/gas/testsuite/gas/i386/prescott.s.pni 2004-06-23 08:06:58.000000000 -0700
+++ binutils/gas/testsuite/gas/i386/prescott.s 2005-11-16 10:58:30.000000000 -0800
@@ -29,4 +29,7 @@ foo:
  mwait
  mwait %eax,%ecx
 
+ addr16 monitor
+ monitor %ax,%ecx,%edx
+
  .p2align 4,0
--- binutils/gas/testsuite/gas/i386/x86-64-prescott.d.pni 2005-11-15 15:33:49.000000000 -0800
+++ binutils/gas/testsuite/gas/i386/x86-64-prescott.d 2005-11-16 17:35:10.000000000 -0800
@@ -0,0 +1,37 @@
+#objdump: -dw
+#name: x86-64 prescott
+
+.*: +file format .*
+
+Disassembly of section .text:
+
+0+000 <foo>:
+   0: 66 0f d0 01 [ ]*addsubpd \(%rcx\),%xmm0
+   4: 66 0f d0 ca [ ]*addsubpd %xmm2,%xmm1
+   8: f2 0f d0 13 [ ]*addsubps \(%rbx\),%xmm2
+   c: f2 0f d0 dc [ ]*addsubps %xmm4,%xmm3
+  10: df 88 90 90 90 90 [ ]*fisttp 0xffffffff90909090\(%rax\)
+  16: db 88 90 90 90 90 [ ]*fisttpl 0xffffffff90909090\(%rax\)
+  1c: dd 88 90 90 90 90 [ ]*fisttpll 0xffffffff90909090\(%rax\)
+  22: 66 0f 7c 65 00 [ ]*haddpd 0x0\(%rbp\),%xmm4
+  27: 66 0f 7c ee [ ]*haddpd %xmm6,%xmm5
+  2b: f2 0f 7c 37 [ ]*haddps \(%rdi\),%xmm6
+  2f: f2 0f 7c f8 [ ]*haddps %xmm0,%xmm7
+  33: 66 0f 7d c1 [ ]*hsubpd %xmm1,%xmm0
+  37: 66 0f 7d 0a [ ]*hsubpd \(%rdx\),%xmm1
+  3b: f2 0f 7d d2 [ ]*hsubps %xmm2,%xmm2
+  3f: f2 0f 7d 1c 24 [ ]*hsubps \(%rsp\),%xmm3
+  44: f2 0f f0 2e [ ]*lddqu  \(%rsi\),%xmm5
+  48: 0f 01 c8 [ ]*monitor %rax,%rcx,%rdx
+  4b: 0f 01 c8 [ ]*monitor %rax,%rcx,%rdx
+  4e: f2 0f 12 f7 [ ]*movddup %xmm7,%xmm6
+  52: f2 0f 12 38 [ ]*movddup \(%rax\),%xmm7
+  56: f3 0f 16 01 [ ]*movshdup \(%rcx\),%xmm0
+  5a: f3 0f 16 ca [ ]*movshdup %xmm2,%xmm1
+  5e: f3 0f 12 13 [ ]*movsldup \(%rbx\),%xmm2
+  62: f3 0f 12 dc [ ]*movsldup %xmm4,%xmm3
+  66: 0f 01 c9 [ ]*mwait  %rax,%rcx
+  69: 0f 01 c9 [ ]*mwait  %rax,%rcx
+  6c: 67 0f 01 c8 [ ]*addr32 monitor %eax,%rcx,%rdx
+  70: 67 0f 01 c8 [ ]*addr32 monitor %eax,%rcx,%rdx
+ ...
--- binutils/gas/testsuite/gas/i386/x86-64-prescott.s.pni 2005-11-15 15:33:47.000000000 -0800
+++ binutils/gas/testsuite/gas/i386/x86-64-prescott.s 2005-11-16 17:31:19.000000000 -0800
@@ -0,0 +1,35 @@
+#Prescott New Instructions
+
+ .text
+foo:
+ addsubpd (%rcx),%xmm0
+ addsubpd %xmm2,%xmm1
+ addsubps (%rbx),%xmm2
+ addsubps %xmm4,%xmm3
+ fisttp 0x90909090(%rax)
+ fisttpl 0x90909090(%rax)
+ fisttpll 0x90909090(%rax)
+ haddpd 0x0(%rbp),%xmm4
+ haddpd %xmm6,%xmm5
+ haddps (%rdi),%xmm6
+ haddps %xmm0,%xmm7
+ hsubpd %xmm1,%xmm0
+ hsubpd (%rdx),%xmm1
+ hsubps %xmm2,%xmm2
+ hsubps (%rsp,1),%xmm3
+ lddqu (%rsi),%xmm5
+ monitor
+ monitor %rax,%rcx,%rdx
+ movddup %xmm7,%xmm6
+ movddup (%rax),%xmm7
+ movshdup (%rcx),%xmm0
+ movshdup %xmm2,%xmm1
+ movsldup (%rbx),%xmm2
+ movsldup %xmm4,%xmm3
+ mwait
+ mwait %rax,%rcx
+
+ addr32 monitor
+ monitor %eax,%rcx,%rdx
+
+ .p2align 4,0
--- binutils/include/opcode/i386.h.pni 2005-07-27 08:41:15.000000000 -0700
+++ binutils/include/opcode/i386.h 2005-11-16 17:37:05.000000000 -0800
@@ -1346,14 +1346,22 @@ static const template i386_optab[] =
 {"hsubps",    2, 0xf20f7d,  X, CpuPNI, NoSuf|IgnoreSize|Modrm, { RegXMM|LLongMem, RegXMM, 0 } },
 {"lddqu",     2, 0xf20ff0,  X, CpuPNI, NoSuf|IgnoreSize|Modrm, { LLongMem, RegXMM, 0 } },
 {"monitor",   0, 0x0f01, 0xc8, CpuPNI, NoSuf|ImmExt, { 0, 0, 0} },
+/* Need to ensure only "monitor %ax,%ecx,%edx" is accepted. */
+{"monitor",   3, 0x670f01, 0xc8, CpuPNI|CpuNo64, NoSuf|ImmExt, { Reg16, Reg32, Reg32 } },
 /* Need to ensure only "monitor %eax,%ecx,%edx" is accepted. */
-{"monitor",   3, 0x0f01, 0xc8, CpuPNI, NoSuf|ImmExt, { Reg32, Reg32, Reg32} },
+{"monitor",   3, 0x0f01, 0xc8, CpuPNI|CpuNo64, NoSuf|ImmExt, { Reg32, Reg32, Reg32 } },
+/* Need to ensure only "monitor %eax,%rcx,%rdx" is accepted. */
+{"monitor",   3, 0x670f01, 0xc8, CpuPNI|Cpu64, NoSuf|ImmExt|NoRex64, { Reg32, Reg64, Reg64 } },
+/* Need to ensure only "monitor %rax,%rcx,%rdx" is accepted. */
+{"monitor",   3, 0x0f01, 0xc8, CpuPNI|Cpu64, NoSuf|ImmExt|NoRex64, { Reg64, Reg64, Reg64 } },
 {"movddup",   2, 0xf20f12,  X, CpuPNI, NoSuf|IgnoreSize|Modrm, { RegXMM|LLongMem, RegXMM, 0 } },
 {"movshdup",  2, 0xf30f16,  X, CpuPNI, NoSuf|IgnoreSize|Modrm, { RegXMM|LLongMem, RegXMM, 0 } },
 {"movsldup",  2, 0xf30f12,  X, CpuPNI, NoSuf|IgnoreSize|Modrm, { RegXMM|LLongMem, RegXMM, 0 } },
 {"mwait",     0, 0x0f01, 0xc9, CpuPNI, NoSuf|ImmExt, { 0, 0, 0} },
 /* Need to ensure only "mwait %eax,%ecx" is accepted.  */
-{"mwait",     2, 0x0f01, 0xc9, CpuPNI, NoSuf|ImmExt, { Reg32, Reg32, 0} },
+{"mwait",     2, 0x0f01, 0xc9, CpuPNI|CpuNo64, NoSuf|ImmExt, { Reg32, Reg32, 0} },
+/* Need to ensure only "mwait %rax,%rcx" is accepted.  */
+{"mwait",     2, 0x0f01, 0xc9, CpuPNI|Cpu64, NoSuf|ImmExt|NoRex64, { Reg64, Reg64, 0} },
 
 /* VMX instructions.  */
 {"vmcall",    0, 0x0f01, 0xc1, CpuVMX, NoSuf|ImmExt, { 0, 0, 0} },
--- binutils/opcodes/i386-dis.c.pni 2005-11-11 10:48:50.000000000 -0800
+++ binutils/opcodes/i386-dis.c 2005-11-16 17:31:55.000000000 -0800
@@ -4413,6 +4413,7 @@ PNI_Fixup (int extrachar ATTRIBUTE_UNUSE
     {
       /* Override "sidt".  */
       char *p = obuf + strlen (obuf) - 4;
+      const char **names = mode_64bit ? names64 : names32;
 
       /* We might have a suffix when disassembling with -Msuffix.  */
       if (*p == 'i')
@@ -4423,7 +4424,7 @@ PNI_Fixup (int extrachar ATTRIBUTE_UNUSE
   /* mwait %eax,%ecx  */
   strcpy (p, "mwait");
   if (!intel_syntax)
-    strcpy (op1out, names32[0]);
+    strcpy (op1out, names[0]);
  }
       else
  {
@@ -4431,21 +4432,21 @@ PNI_Fixup (int extrachar ATTRIBUTE_UNUSE
   strcpy (p, "monitor");
   if (!intel_syntax)
     {
-      if (!mode_64bit)
- strcpy (op1out, names32[0]);
-      else if (!(prefixes & PREFIX_ADDR))
- strcpy (op1out, names64[0]);
+      const char **names_with_addr_prefix;
+      names_with_addr_prefix = mode_64bit ? names32 : names16;
+      if (!(prefixes & PREFIX_ADDR))
+ strcpy (op1out, names[0]);
       else
  {
-  strcpy (op1out, names32[0]);
+  strcpy (op1out, names_with_addr_prefix[0]);
   used_prefixes |= PREFIX_ADDR;
  }
-      strcpy (op3out, names32[2]);
+      strcpy (op3out, names[2]);
     }
  }
       if (!intel_syntax)
  {
-  strcpy (op2out, names32[1]);
+  strcpy (op2out, names[1]);
   two_source_ops = 1;
  }
 
Reply | Threaded
Open this post in threaded view
|

Re: PATCH: PR gas/1874: mwait/monitor don't work in 64bit

Jan Beulich
>Here is the information I got from our chip people. The address size
>override prefix is honored for "monitor" in both 16 and 32bit modes.
>In 64bit mode, RCX and RDX are used for "monitor", RAX and RCX are
>used for "mwait". This patch implements it.

Indeed, monitor and mwait GP-fault on non-zero RCX (but zero ECX) in
64-bit mode (regardless of address size override). In addition to what
you say (but consistent with what your new tests implement) monitor also
honors the address size override in 64-bit mode. Further, even in 16-bit
mode (and thus I suppose also in 32-bit mode), use of the operand size
override causes a (presumably #UD) fault (the manual mentions this only
for 64-bit mode).

Bottom line is the documentation really doesn't match actual behavior.

However, I also have doubts that in 16-bit mode the address size
handling is as you say: Using a value of 0x80000000 for eax doesn't
produce a #GP fault regardless of the use of an address size override.

Regarding the patch, I don't think hard-coding the address size
override for 16-bit operation of monitor is appropriate - under .code16
this is not going to produce the desired effect (and likewise is the
opposite 32-bit operation in 16-bit mode then missing the override). The
base problem here is that monitor's address operand, when explicitly
specified, should take the form of a memory operand rather than a plain
register (and note that the SDM doesn't indicate any particular syntax
for how the operands should be specified). Once that is done, the
address size prefixing will come out right implicitly, and the
restriction to only use %ax/%eax/%rax could be easily added to the code
in i386_index_check that already deals with AMD's SVME instructions that
have the same restriction (except that they also ignore segment
overrides, which monitor doesn't).

Further, for the disassembly part I'd really like to see the explicit
addr16/addr32 displaying to go away; these should only be output on
instructions where none of the operands indicates the address size
used.

Jan
Reply | Threaded
Open this post in threaded view
|

Re: PATCH: PR gas/1874: mwait/monitor don't work in 64bit

H.J. Lu-27
On Thu, Nov 17, 2005 at 10:30:05AM +0100, Jan Beulich wrote:

> >Here is the information I got from our chip people. The address size
> >override prefix is honored for "monitor" in both 16 and 32bit modes.
> >In 64bit mode, RCX and RDX are used for "monitor", RAX and RCX are
> >used for "mwait". This patch implements it.
>
> Indeed, monitor and mwait GP-fault on non-zero RCX (but zero ECX) in
> 64-bit mode (regardless of address size override). In addition to what
> you say (but consistent with what your new tests implement) monitor also
> honors the address size override in 64-bit mode. Further, even in 16-bit
> mode (and thus I suppose also in 32-bit mode), use of the operand size
> override causes a (presumably #UD) fault (the manual mentions this only
> for 64-bit mode).
>
> Bottom line is the documentation really doesn't match actual behavior.
>
> However, I also have doubts that in 16-bit mode the address size
> handling is as you say: Using a value of 0x80000000 for eax doesn't
> produce a #GP fault regardless of the use of an address size override.


Ooops. I meant to say "The address size override prefix is honored for
monitor in both 32bit and 64bit modes." BTW, the current processsor
only checks edx/32bit for monitor and eax/32bit for mwait in 64bit
mode. But it isn't guaranteed for future processors.

>
> Regarding the patch, I don't think hard-coding the address size
> override for 16-bit operation of monitor is appropriate - under .code16
> this is not going to produce the desired effect (and likewise is the
> opposite 32-bit operation in 16-bit mode then missing the override). The
> base problem here is that monitor's address operand, when explicitly
> specified, should take the form of a memory operand rather than a plain
> register (and note that the SDM doesn't indicate any particular syntax
> for how the operands should be specified). Once that is done, the
> address size prefixing will come out right implicitly, and the
> restriction to only use %ax/%eax/%rax could be easily added to the code
> in i386_index_check that already deals with AMD's SVME instructions that
> have the same restriction (except that they also ignore segment
> overrides, which monitor doesn't).

I will check.

>
> Further, for the disassembly part I'd really like to see the explicit
> addr16/addr32 displaying to go away; these should only be output on
> instructions where none of the operands indicates the address size
> used.

Well, the Intel mode only displays "monitor/mwait" then.


H.J.
Reply | Threaded
Open this post in threaded view
|

Re: PATCH: PR gas/1874: mwait/monitor don't work in 64bit

Jan Beulich
>> Further, for the disassembly part I'd really like to see the
explicit
>> addr16/addr32 displaying to go away; these should only be output on
>> instructions where none of the operands indicates the address size
>> used.
>
>Well, the Intel mode only displays "monitor/mwait" then.

Which I ought to fix if that's the case...

Jan
Reply | Threaded
Open this post in threaded view
|

Re: PATCH: PR gas/1874: mwait/monitor don't work in 64bit

H.J. Lu-27
In reply to this post by Jan Beulich
On Thu, Nov 17, 2005 at 10:30:05AM +0100, Jan Beulich wrote:
>
> Regarding the patch, I don't think hard-coding the address size
> override for 16-bit operation of monitor is appropriate - under .code16
> this is not going to produce the desired effect (and likewise is the
> opposite 32-bit operation in 16-bit mode then missing the override). The
> base problem here is that monitor's address operand, when explicitly

The opcode is the same for both 32bit and 64bit modes. The address
 size ovverride only changes the size of EAX/RAX. I don't see how
".code16" can be used with it. As for ".code32", it works fine:

[hjl@gnu-13 gas]$ cat x.s
        .code32
        monitor %eax,%ecx,%edx
        .code64
        monitor %rax,%rcx,%rdx
[hjl@gnu-13 gas]$ ./as-new -o x.o x.s
[hjl@gnu-13 gas]$ ../binutils/objdump -d x.o

x.o:     file format elf64-x86-64

Disassembly of section .text:

0000000000000000 <.text>:
   0:   0f 01 c8                monitor %rax,%rcx,%rdx
   3:   0f 01 c8                monitor %rax,%rcx,%rdx


>
> Further, for the disassembly part I'd really like to see the explicit
> addr16/addr32 displaying to go away; these should only be output on
> instructions where none of the operands indicates the address size
> used.
>

Here is the new patch to do it.


H.J.
----
gas/testsuite/

2005-11-17  H.J. Lu  <[hidden email]>

        PR gas/1874
        * gas/i386/i386.exp: Add x86-64-prescott for 64bit.

        * gas/i386/prescott.s: Test address size override for monitor.
        * gas/i386/prescott.d: Updated.

        * gas/i386/x86-64-prescott.d: New file.
        * gas/i386/x86-64-prescott.s: Likewise.

include/opcode/

2005-11-17  H.J. Lu  <[hidden email]>

        PR gas/1874
        * i386.h (i386_optab): Add 64bit support for monitor and
        mwait. Add address size override support for monitor.

opcodes/

2005-11-17  H.J. Lu  <[hidden email]>

        PR gas/1874
        * i386-dis.c (PNI_Fixup): Add 64bit and address size override
        support for monitor and mwait.

--- binutils/gas/testsuite/gas/i386/i386.exp.pni 2005-11-11 10:48:53.000000000 -0800
+++ binutils/gas/testsuite/gas/i386/i386.exp 2005-11-15 15:37:50.000000000 -0800
@@ -131,6 +131,7 @@ if [expr ([istarget "i*86-*-*"] || [ista
     run_dump_test "svme64"
     run_dump_test "x86-64-vmx"
     run_dump_test "immed64"
+    run_dump_test "x86-64-prescott"
 
     # For ELF targets verify that @unwind works.
     if { ([istarget "*-*-elf*"] || [istarget "*-*-linux*"]
--- binutils/gas/testsuite/gas/i386/prescott.d.pni 2004-06-23 08:06:57.000000000 -0700
+++ binutils/gas/testsuite/gas/i386/prescott.d 2005-11-17 08:29:36.000000000 -0800
@@ -32,5 +32,6 @@ Disassembly of section .text:
   62: f3 0f 12 dc [ ]*movsldup %xmm4,%xmm3
   66: 0f 01 c9 [ ]*mwait  %eax,%ecx
   69: 0f 01 c9 [ ]*mwait  %eax,%ecx
-  6c: 00 00 [ ]*add    %al,\(%eax\)
+  6c: 67 0f 01 c8 [ ]*monitor %ax,%ecx,%edx
+  70: 67 0f 01 c8 [ ]*monitor %ax,%ecx,%edx
  ...
--- binutils/gas/testsuite/gas/i386/prescott.s.pni 2004-06-23 08:06:58.000000000 -0700
+++ binutils/gas/testsuite/gas/i386/prescott.s 2005-11-16 10:58:30.000000000 -0800
@@ -29,4 +29,7 @@ foo:
  mwait
  mwait %eax,%ecx
 
+ addr16 monitor
+ monitor %ax,%ecx,%edx
+
  .p2align 4,0
--- binutils/gas/testsuite/gas/i386/x86-64-prescott.d.pni 2005-11-15 15:33:49.000000000 -0800
+++ binutils/gas/testsuite/gas/i386/x86-64-prescott.d 2005-11-17 08:29:42.000000000 -0800
@@ -0,0 +1,37 @@
+#objdump: -dw
+#name: x86-64 prescott
+
+.*: +file format .*
+
+Disassembly of section .text:
+
+0+000 <foo>:
+   0: 66 0f d0 01 [ ]*addsubpd \(%rcx\),%xmm0
+   4: 66 0f d0 ca [ ]*addsubpd %xmm2,%xmm1
+   8: f2 0f d0 13 [ ]*addsubps \(%rbx\),%xmm2
+   c: f2 0f d0 dc [ ]*addsubps %xmm4,%xmm3
+  10: df 88 90 90 90 90 [ ]*fisttp 0xffffffff90909090\(%rax\)
+  16: db 88 90 90 90 90 [ ]*fisttpl 0xffffffff90909090\(%rax\)
+  1c: dd 88 90 90 90 90 [ ]*fisttpll 0xffffffff90909090\(%rax\)
+  22: 66 0f 7c 65 00 [ ]*haddpd 0x0\(%rbp\),%xmm4
+  27: 66 0f 7c ee [ ]*haddpd %xmm6,%xmm5
+  2b: f2 0f 7c 37 [ ]*haddps \(%rdi\),%xmm6
+  2f: f2 0f 7c f8 [ ]*haddps %xmm0,%xmm7
+  33: 66 0f 7d c1 [ ]*hsubpd %xmm1,%xmm0
+  37: 66 0f 7d 0a [ ]*hsubpd \(%rdx\),%xmm1
+  3b: f2 0f 7d d2 [ ]*hsubps %xmm2,%xmm2
+  3f: f2 0f 7d 1c 24 [ ]*hsubps \(%rsp\),%xmm3
+  44: f2 0f f0 2e [ ]*lddqu  \(%rsi\),%xmm5
+  48: 0f 01 c8 [ ]*monitor %rax,%rcx,%rdx
+  4b: 0f 01 c8 [ ]*monitor %rax,%rcx,%rdx
+  4e: f2 0f 12 f7 [ ]*movddup %xmm7,%xmm6
+  52: f2 0f 12 38 [ ]*movddup \(%rax\),%xmm7
+  56: f3 0f 16 01 [ ]*movshdup \(%rcx\),%xmm0
+  5a: f3 0f 16 ca [ ]*movshdup %xmm2,%xmm1
+  5e: f3 0f 12 13 [ ]*movsldup \(%rbx\),%xmm2
+  62: f3 0f 12 dc [ ]*movsldup %xmm4,%xmm3
+  66: 0f 01 c9 [ ]*mwait  %rax,%rcx
+  69: 0f 01 c9 [ ]*mwait  %rax,%rcx
+  6c: 67 0f 01 c8 [ ]*monitor %eax,%rcx,%rdx
+  70: 67 0f 01 c8 [ ]*monitor %eax,%rcx,%rdx
+ ...
--- binutils/gas/testsuite/gas/i386/x86-64-prescott.s.pni 2005-11-15 15:33:47.000000000 -0800
+++ binutils/gas/testsuite/gas/i386/x86-64-prescott.s 2005-11-16 17:31:19.000000000 -0800
@@ -0,0 +1,35 @@
+#Prescott New Instructions
+
+ .text
+foo:
+ addsubpd (%rcx),%xmm0
+ addsubpd %xmm2,%xmm1
+ addsubps (%rbx),%xmm2
+ addsubps %xmm4,%xmm3
+ fisttp 0x90909090(%rax)
+ fisttpl 0x90909090(%rax)
+ fisttpll 0x90909090(%rax)
+ haddpd 0x0(%rbp),%xmm4
+ haddpd %xmm6,%xmm5
+ haddps (%rdi),%xmm6
+ haddps %xmm0,%xmm7
+ hsubpd %xmm1,%xmm0
+ hsubpd (%rdx),%xmm1
+ hsubps %xmm2,%xmm2
+ hsubps (%rsp,1),%xmm3
+ lddqu (%rsi),%xmm5
+ monitor
+ monitor %rax,%rcx,%rdx
+ movddup %xmm7,%xmm6
+ movddup (%rax),%xmm7
+ movshdup (%rcx),%xmm0
+ movshdup %xmm2,%xmm1
+ movsldup (%rbx),%xmm2
+ movsldup %xmm4,%xmm3
+ mwait
+ mwait %rax,%rcx
+
+ addr32 monitor
+ monitor %eax,%rcx,%rdx
+
+ .p2align 4,0
--- binutils/include/opcode/i386.h.pni 2005-07-27 08:41:15.000000000 -0700
+++ binutils/include/opcode/i386.h 2005-11-17 08:05:35.000000000 -0800
@@ -1346,14 +1346,22 @@ static const template i386_optab[] =
 {"hsubps",    2, 0xf20f7d,  X, CpuPNI, NoSuf|IgnoreSize|Modrm, { RegXMM|LLongMem, RegXMM, 0 } },
 {"lddqu",     2, 0xf20ff0,  X, CpuPNI, NoSuf|IgnoreSize|Modrm, { LLongMem, RegXMM, 0 } },
 {"monitor",   0, 0x0f01, 0xc8, CpuPNI, NoSuf|ImmExt, { 0, 0, 0} },
+/* Need to ensure only "monitor %ax,%ecx,%edx" is accepted. */
+{"monitor",   3, 0x670f01, 0xc8, CpuPNI|CpuNo64, NoSuf|ImmExt, { Reg16, Reg32, Reg32 } },
 /* Need to ensure only "monitor %eax,%ecx,%edx" is accepted. */
-{"monitor",   3, 0x0f01, 0xc8, CpuPNI, NoSuf|ImmExt, { Reg32, Reg32, Reg32} },
+{"monitor",   3, 0x0f01, 0xc8, CpuPNI|CpuNo64, NoSuf|ImmExt, { Reg32, Reg32, Reg32 } },
+/* Need to ensure only "monitor %eax,%rcx,%rdx" is accepted. */
+{"monitor",   3, 0x670f01, 0xc8, CpuPNI|Cpu64, NoSuf|ImmExt|NoRex64, { Reg32, Reg64, Reg64 } },
+/* Need to ensure only "monitor %rax,%rcx,%rdx" is accepted. */
+{"monitor",   3, 0x0f01, 0xc8, CpuPNI|Cpu64, NoSuf|ImmExt|NoRex64, { Reg64, Reg64, Reg64 } },
 {"movddup",   2, 0xf20f12,  X, CpuPNI, NoSuf|IgnoreSize|Modrm, { RegXMM|LLongMem, RegXMM, 0 } },
 {"movshdup",  2, 0xf30f16,  X, CpuPNI, NoSuf|IgnoreSize|Modrm, { RegXMM|LLongMem, RegXMM, 0 } },
 {"movsldup",  2, 0xf30f12,  X, CpuPNI, NoSuf|IgnoreSize|Modrm, { RegXMM|LLongMem, RegXMM, 0 } },
 {"mwait",     0, 0x0f01, 0xc9, CpuPNI, NoSuf|ImmExt, { 0, 0, 0} },
 /* Need to ensure only "mwait %eax,%ecx" is accepted.  */
-{"mwait",     2, 0x0f01, 0xc9, CpuPNI, NoSuf|ImmExt, { Reg32, Reg32, 0} },
+{"mwait",     2, 0x0f01, 0xc9, CpuPNI|CpuNo64, NoSuf|ImmExt, { Reg32, Reg32, 0} },
+/* Need to ensure only "mwait %rax,%rcx" is accepted.  */
+{"mwait",     2, 0x0f01, 0xc9, CpuPNI|Cpu64, NoSuf|ImmExt|NoRex64, { Reg64, Reg64, 0} },
 
 /* VMX instructions.  */
 {"vmcall",    0, 0x0f01, 0xc1, CpuVMX, NoSuf|ImmExt, { 0, 0, 0} },
--- binutils/opcodes/i386-dis.c.pni 2005-11-11 10:48:50.000000000 -0800
+++ binutils/opcodes/i386-dis.c 2005-11-17 08:32:00.000000000 -0800
@@ -4412,18 +4412,30 @@ PNI_Fixup (int extrachar ATTRIBUTE_UNUSE
   if (mod == 3 && reg == 1 && rm <= 1)
     {
       /* Override "sidt".  */
-      char *p = obuf + strlen (obuf) - 4;
+      size_t olen = strlen (obuf);
+      char *p = obuf + olen - 4;
+      const char **names = mode_64bit ? names64 : names32;
 
       /* We might have a suffix when disassembling with -Msuffix.  */
       if (*p == 'i')
  --p;
 
+      /* Remove "addr16/addr32" if we aren't in Intel mode.  */
+      if (!intel_syntax
+  && (prefixes & PREFIX_ADDR)
+  && olen >= (4 + 7)
+  && *(p - 1) == ' '
+  && strncmp (p - 7, "addr", 4) == 0
+  && (strncmp (p - 3, "16", 2) == 0
+      || strncmp (p - 3, "32", 2) == 0))
+ p -= 7;
+
       if (rm)
  {
   /* mwait %eax,%ecx  */
   strcpy (p, "mwait");
   if (!intel_syntax)
-    strcpy (op1out, names32[0]);
+    strcpy (op1out, names[0]);
  }
       else
  {
@@ -4431,21 +4443,21 @@ PNI_Fixup (int extrachar ATTRIBUTE_UNUSE
   strcpy (p, "monitor");
   if (!intel_syntax)
     {
-      if (!mode_64bit)
- strcpy (op1out, names32[0]);
-      else if (!(prefixes & PREFIX_ADDR))
- strcpy (op1out, names64[0]);
+      const char **names_with_addr_prefix;
+      names_with_addr_prefix = mode_64bit ? names32 : names16;
+      if (!(prefixes & PREFIX_ADDR))
+ strcpy (op1out, names[0]);
       else
  {
-  strcpy (op1out, names32[0]);
+  strcpy (op1out, names_with_addr_prefix[0]);
   used_prefixes |= PREFIX_ADDR;
  }
-      strcpy (op3out, names32[2]);
+      strcpy (op3out, names[2]);
     }
  }
       if (!intel_syntax)
  {
-  strcpy (op2out, names32[1]);
+  strcpy (op2out, names[1]);
   two_source_ops = 1;
  }
 
Reply | Threaded
Open this post in threaded view
|

Re: PATCH: PR gas/1874: mwait/monitor don't work in 64bit

Jan Beulich
>>> "H. J. Lu" <[hidden email]> 17.11.05 17:44:06 >>>
>On Thu, Nov 17, 2005 at 10:30:05AM +0100, Jan Beulich wrote:
>>
>> Regarding the patch, I don't think hard-coding the address size
>> override for 16-bit operation of monitor is appropriate - under
.code16
>> this is not going to produce the desired effect (and likewise is
the
>> opposite 32-bit operation in 16-bit mode then missing the override).
The
>> base problem here is that monitor's address operand, when
explicitly
>
>The opcode is the same for both 32bit and 64bit modes. The address
> size ovverride only changes the size of EAX/RAX. I don't see how
>".code16" can be used with it. As for ".code32", it works fine:

Why shouldn't BIOS code be using this? This would likely require
.code16.

Jan
Reply | Threaded
Open this post in threaded view
|

Re: PATCH: PR gas/1874: mwait/monitor don't work in 64bit

H.J. Lu-27
On Thu, Nov 17, 2005 at 06:05:57PM +0100, Jan Beulich wrote:

> >>> "H. J. Lu" <[hidden email]> 17.11.05 17:44:06 >>>
> >On Thu, Nov 17, 2005 at 10:30:05AM +0100, Jan Beulich wrote:
> >>
> >> Regarding the patch, I don't think hard-coding the address size
> >> override for 16-bit operation of monitor is appropriate - under
> .code16
> >> this is not going to produce the desired effect (and likewise is
> the
> >> opposite 32-bit operation in 16-bit mode then missing the override).
> The
> >> base problem here is that monitor's address operand, when
> explicitly
> >
> >The opcode is the same for both 32bit and 64bit modes. The address
> > size ovverride only changes the size of EAX/RAX. I don't see how
> >".code16" can be used with it. As for ".code32", it works fine:
>
> Why shouldn't BIOS code be using this? This would likely require
> .code16.
>

monitor/mwait work in 16bit mode. The address size override prefix can
be used to change the AX size. This patch support memory as the first
operand of monitor.

-----
gas/

2005-11-17  H.J. Lu  <[hidden email]>

        * config/tc-i386.c (md_assemble): Don't check the first operand of
        "monitor/mwait" if it isn't a register.
        (process_suffix): Handle monitor for 16bit mode.
        (i386_index_check): Handle monitor.

gas/testsuite/

2005-11-17  H.J. Lu  <[hidden email]>

        PR gas/1874
        * gas/i386/i386.exp: Add x86-64-prescott for 64bit.

        * gas/i386/prescott.s: Test new monitor syntax. Test address
        size override for monitor.
        * gas/i386/prescott.d: Updated.

        * gas/i386/suffix.d: Updated.

        * gas/i386/x86-64-prescott.d: New file.
        * gas/i386/x86-64-prescott.s: Likewise.

include/opcode/

2005-11-17  H.J. Lu  <[hidden email]>

        PR gas/1874
        * i386.h (i386_optab): Support memory as the first operand of
        monitor. Add 64bit support for monitor and mwait.

opcodes/

2005-11-17  H.J. Lu  <[hidden email]>

        PR gas/1874
        * configure.in (AC_GNU_SOURCE): Added.
        (AC_CHECK_DECLS): Add stpcpy.
        * configure: Regenerated.
        * config.in: Likewise.

        * i386-dis.c (PNI_Fixup): Change the the first operand of
        monitor to memory. Add 64bit and address size override support
        for monitor and mwait.

        * sysdep.h (stpcpy): Declare if HAVE_DECL_STPCPY isn't defined.

--- binutils/gas/config/tc-i386.c.pni 2005-11-11 10:48:52.000000000 -0800
+++ binutils/gas/config/tc-i386.c 2005-11-17 11:56:03.000000000 -0800
@@ -1538,7 +1538,7 @@ md_assemble (line)
   unsigned int x;
 
   for (x = 0; x < i.operands; x++)
-    if (i.op[x].regs->reg_num != x)
+    if (i.op[x].regs && i.op[x].regs->reg_num != x)
       as_bad (_("can't use register '%%%s' as operand %d in '%s'."),
  i.op[x].regs->reg_name, x + 1, i.tm.name);
   i.operands = 0;
@@ -2545,12 +2545,25 @@ process_suffix (void)
       /* 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_DOUBLE_MNEM_SUFFIX
-  && !(i.tm.opcode_modifier & (IgnoreSize | FloatMF))
-  && ((i.suffix == LONG_MNEM_SUFFIX) == (flag_code == CODE_16BIT)
-      || (flag_code == CODE_64BIT
-  && (i.tm.opcode_modifier & JumpByte))))
+      if ((i.tm.cpu_flags & CpuPNI)
+  && i.tm.base_opcode == 0x0f01
+  && i.tm.extension_opcode == 0xc8)
+ {
+  /* monitor in SSE3 is a very special case. In 16bit mode,
+     the default is AX. The address size override prefix is
+     used to indicate EAX.  */
+  if (flag_code == CODE_16BIT
+      && (i.base_reg->reg_type & Reg32)
+      && i.prefix [ADDR_PREFIX] == 0
+      && !add_prefix (ADDR_PREFIX_OPCODE))
+    return 0;
+ }
+      else if (i.suffix != QWORD_MNEM_SUFFIX
+       && i.suffix != LONG_DOUBLE_MNEM_SUFFIX
+       && !(i.tm.opcode_modifier & (IgnoreSize | FloatMF))
+       && ((i.suffix == LONG_MNEM_SUFFIX) == (flag_code == CODE_16BIT)
+   || (flag_code == CODE_64BIT
+       && (i.tm.opcode_modifier & JumpByte))))
  {
   unsigned int prefix = DATA_PREFIX_OPCODE;
 
@@ -4322,6 +4335,28 @@ i386_index_check (operand_string)
   || (i.types[0] & Disp))
  ok = 0;
     }
+  else if ((current_templates->start->cpu_flags & CpuPNI)
+   && current_templates->end[-1].operand_types[0] == AnyMem
+   && current_templates->start->base_opcode == 0x0f01
+   && current_templates->start->extension_opcode == 0xc8)
+    {
+      /* Memory operand of "monitor" is special in that it only allows
+ rAX as their memory address. */
+      unsigned RegXX;
+
+      if (flag_code == CODE_64BIT)
+ RegXX = i.prefix[ADDR_PREFIX] == 0 ? Reg64 : Reg32;
+      else
+ RegXX = (flag_code == CODE_16BIT) ^ (i.prefix[ADDR_PREFIX] != 0)
+ ? Reg16
+ : Reg32;
+      if (!i.base_reg
+  || !(i.base_reg->reg_type & Acc)
+  || !(i.base_reg->reg_type & RegXX)
+  || i.index_reg
+  || (i.types[0] & Disp))
+ ok = 0;
+    }
   else if (flag_code == CODE_64BIT)
      {
        unsigned RegXX = (i.prefix[ADDR_PREFIX] == 0 ? Reg64 : Reg32);
--- binutils/gas/testsuite/gas/i386/i386.exp.pni 2005-11-11 10:48:53.000000000 -0800
+++ binutils/gas/testsuite/gas/i386/i386.exp 2005-11-15 15:37:50.000000000 -0800
@@ -131,6 +131,7 @@ if [expr ([istarget "i*86-*-*"] || [ista
     run_dump_test "svme64"
     run_dump_test "x86-64-vmx"
     run_dump_test "immed64"
+    run_dump_test "x86-64-prescott"
 
     # For ELF targets verify that @unwind works.
     if { ([istarget "*-*-elf*"] || [istarget "*-*-linux*"]
--- binutils/gas/testsuite/gas/i386/prescott.d.pni 2004-06-23 08:06:57.000000000 -0700
+++ binutils/gas/testsuite/gas/i386/prescott.d 2005-11-17 11:33:18.000000000 -0800
@@ -22,8 +22,8 @@ Disassembly of section .text:
   3b: f2 0f 7d d2 [ ]*hsubps %xmm2,%xmm2
   3f: f2 0f 7d 1c 24 [ ]*hsubps \(%esp\),%xmm3
   44: f2 0f f0 2e [ ]*lddqu  \(%esi\),%xmm5
-  48: 0f 01 c8 [ ]*monitor %eax,%ecx,%edx
-  4b: 0f 01 c8 [ ]*monitor %eax,%ecx,%edx
+  48: 0f 01 c8 [ ]*monitor \(%eax\),%ecx,%edx
+  4b: 0f 01 c8 [ ]*monitor \(%eax\),%ecx,%edx
   4e: f2 0f 12 f7 [ ]*movddup %xmm7,%xmm6
   52: f2 0f 12 38 [ ]*movddup \(%eax\),%xmm7
   56: f3 0f 16 01 [ ]*movshdup \(%ecx\),%xmm0
@@ -32,5 +32,7 @@ Disassembly of section .text:
   62: f3 0f 12 dc [ ]*movsldup %xmm4,%xmm3
   66: 0f 01 c9 [ ]*mwait  %eax,%ecx
   69: 0f 01 c9 [ ]*mwait  %eax,%ecx
-  6c: 00 00 [ ]*add    %al,\(%eax\)
+  6c: 0f 01 c8 [ ]*monitor \(%eax\),%ecx,%edx
+  6f: 67 0f 01 c8 [ ]*monitor \(%ax\),%ecx,%edx
+  73: 67 0f 01 c8 [ ]*monitor \(%ax\),%ecx,%edx
  ...
--- binutils/gas/testsuite/gas/i386/prescott.s.pni 2004-06-23 08:06:58.000000000 -0700
+++ binutils/gas/testsuite/gas/i386/prescott.s 2005-11-17 11:31:57.000000000 -0800
@@ -29,4 +29,8 @@ foo:
  mwait
  mwait %eax,%ecx
 
+ monitor (%eax),%ecx,%edx
+ monitor (%ax),%ecx,%edx
+ addr16 monitor
+
  .p2align 4,0
--- binutils/gas/testsuite/gas/i386/suffix.d.pni 2005-07-18 21:11:19.000000000 -0700
+++ binutils/gas/testsuite/gas/i386/suffix.d 2005-11-17 11:34:25.000000000 -0800
@@ -6,7 +6,7 @@
 Disassembly of section .text:
 
 0+000 <foo>:
-   0: 0f 01 c8 [ ]*monitor %eax,%ecx,%edx
+   0: 0f 01 c8 [ ]*monitor \(%eax\),%ecx,%edx
    3: 0f 01 c9 [ ]*mwait  %eax,%ecx
    6: 0f 01 c1 [ ]*vmcall
    9: 0f 01 c2 [ ]*vmlaunch
--- binutils/gas/testsuite/gas/i386/x86-64-prescott.d.pni 2005-11-15 15:33:49.000000000 -0800
+++ binutils/gas/testsuite/gas/i386/x86-64-prescott.d 2005-11-17 11:36:57.000000000 -0800
@@ -0,0 +1,37 @@
+#objdump: -dw
+#name: x86-64 prescott
+
+.*: +file format .*
+
+Disassembly of section .text:
+
+0+000 <foo>:
+   0: 66 0f d0 01 [ ]*addsubpd \(%rcx\),%xmm0
+   4: 66 0f d0 ca [ ]*addsubpd %xmm2,%xmm1
+   8: f2 0f d0 13 [ ]*addsubps \(%rbx\),%xmm2
+   c: f2 0f d0 dc [ ]*addsubps %xmm4,%xmm3
+  10: df 88 90 90 90 90 [ ]*fisttp 0xffffffff90909090\(%rax\)
+  16: db 88 90 90 90 90 [ ]*fisttpl 0xffffffff90909090\(%rax\)
+  1c: dd 88 90 90 90 90 [ ]*fisttpll 0xffffffff90909090\(%rax\)
+  22: 66 0f 7c 65 00 [ ]*haddpd 0x0\(%rbp\),%xmm4
+  27: 66 0f 7c ee [ ]*haddpd %xmm6,%xmm5
+  2b: f2 0f 7c 37 [ ]*haddps \(%rdi\),%xmm6
+  2f: f2 0f 7c f8 [ ]*haddps %xmm0,%xmm7
+  33: 66 0f 7d c1 [ ]*hsubpd %xmm1,%xmm0
+  37: 66 0f 7d 0a [ ]*hsubpd \(%rdx\),%xmm1
+  3b: f2 0f 7d d2 [ ]*hsubps %xmm2,%xmm2
+  3f: f2 0f 7d 1c 24 [ ]*hsubps \(%rsp\),%xmm3
+  44: f2 0f f0 2e [ ]*lddqu  \(%rsi\),%xmm5
+  48: 0f 01 c8 [ ]*monitor \(%rax\),%rcx,%rdx
+  4b: 0f 01 c8 [ ]*monitor \(%rax\),%rcx,%rdx
+  4e: f2 0f 12 f7 [ ]*movddup %xmm7,%xmm6
+  52: f2 0f 12 38 [ ]*movddup \(%rax\),%xmm7
+  56: f3 0f 16 01 [ ]*movshdup \(%rcx\),%xmm0
+  5a: f3 0f 16 ca [ ]*movshdup %xmm2,%xmm1
+  5e: f3 0f 12 13 [ ]*movsldup \(%rbx\),%xmm2
+  62: f3 0f 12 dc [ ]*movsldup %xmm4,%xmm3
+  66: 0f 01 c9 [ ]*mwait  %rax,%rcx
+  69: 0f 01 c9 [ ]*mwait  %rax,%rcx
+  6c: 67 0f 01 c8 [ ]*monitor \(%eax\),%rcx,%rdx
+  70: 67 0f 01 c8 [ ]*monitor \(%eax\),%rcx,%rdx
+ ...
--- binutils/gas/testsuite/gas/i386/x86-64-prescott.s.pni 2005-11-15 15:33:47.000000000 -0800
+++ binutils/gas/testsuite/gas/i386/x86-64-prescott.s 2005-11-17 11:35:47.000000000 -0800
@@ -0,0 +1,35 @@
+#Prescott New Instructions
+
+ .text
+foo:
+ addsubpd (%rcx),%xmm0
+ addsubpd %xmm2,%xmm1
+ addsubps (%rbx),%xmm2
+ addsubps %xmm4,%xmm3
+ fisttp 0x90909090(%rax)
+ fisttpl 0x90909090(%rax)
+ fisttpll 0x90909090(%rax)
+ haddpd 0x0(%rbp),%xmm4
+ haddpd %xmm6,%xmm5
+ haddps (%rdi),%xmm6
+ haddps %xmm0,%xmm7
+ hsubpd %xmm1,%xmm0
+ hsubpd (%rdx),%xmm1
+ hsubps %xmm2,%xmm2
+ hsubps (%rsp,1),%xmm3
+ lddqu (%rsi),%xmm5
+ monitor
+ monitor (%rax),%rcx,%rdx
+ movddup %xmm7,%xmm6
+ movddup (%rax),%xmm7
+ movshdup (%rcx),%xmm0
+ movshdup %xmm2,%xmm1
+ movsldup (%rbx),%xmm2
+ movsldup %xmm4,%xmm3
+ mwait
+ mwait %rax,%rcx
+
+ monitor (%eax),%rcx,%rdx
+ addr32 monitor
+
+ .p2align 4,0
--- binutils/include/opcode/i386.h.pni 2005-07-27 08:41:15.000000000 -0700
+++ binutils/include/opcode/i386.h 2005-11-17 11:44:31.000000000 -0800
@@ -1346,14 +1346,29 @@ static const template i386_optab[] =
 {"hsubps",    2, 0xf20f7d,  X, CpuPNI, NoSuf|IgnoreSize|Modrm, { RegXMM|LLongMem, RegXMM, 0 } },
 {"lddqu",     2, 0xf20ff0,  X, CpuPNI, NoSuf|IgnoreSize|Modrm, { LLongMem, RegXMM, 0 } },
 {"monitor",   0, 0x0f01, 0xc8, CpuPNI, NoSuf|ImmExt, { 0, 0, 0} },
-/* Need to ensure only "monitor %eax,%ecx,%edx" is accepted. */
-{"monitor",   3, 0x0f01, 0xc8, CpuPNI, NoSuf|ImmExt, { Reg32, Reg32, Reg32} },
+/* monitor is very special. CX and DX are always 64bits with zero upper
+   32bits in 64bit mode, and 32bits in 16bit and 32bit modes. The
+   address size override prefix can be used to overrride the AX size in
+   all modes.  */
+/* The old syntax for 32bit only. Need to ensure only
+   "monitor %eax,%ecx,%edx" is accepted. */
+{"monitor",   3, 0x0f01, 0xc8, CpuPNI|CpuNo64, NoSuf|ImmExt, { Reg32, Reg32, Reg32 } },
+/* The new syntax for 32bit. Need to ensure only
+   "monitor (%eax)/(%ax),%ecx,%edx" is accepted. */
+{"monitor",   3, 0x0f01, 0xc8, CpuPNI|CpuNo64, NoSuf|ImmExt, { AnyMem, Reg32, Reg32 } },
+/* The syntax for 64bit. Need to ensure only
+   "monitor (%rax)/(%eax),%rcx,%rdx" is accepted. */
+{"monitor",   3, 0x0f01, 0xc8, CpuPNI|Cpu64, NoSuf|ImmExt|NoRex64, { AnyMem, Reg64, Reg64 } },
 {"movddup",   2, 0xf20f12,  X, CpuPNI, NoSuf|IgnoreSize|Modrm, { RegXMM|LLongMem, RegXMM, 0 } },
 {"movshdup",  2, 0xf30f16,  X, CpuPNI, NoSuf|IgnoreSize|Modrm, { RegXMM|LLongMem, RegXMM, 0 } },
 {"movsldup",  2, 0xf30f12,  X, CpuPNI, NoSuf|IgnoreSize|Modrm, { RegXMM|LLongMem, RegXMM, 0 } },
 {"mwait",     0, 0x0f01, 0xc9, CpuPNI, NoSuf|ImmExt, { 0, 0, 0} },
+/* mwait is very special. AX and CX are always 64bits with zero upper
+   32bits in 64bit mode, and 32bits in 16bit and 32bit modes.  */
 /* Need to ensure only "mwait %eax,%ecx" is accepted.  */
-{"mwait",     2, 0x0f01, 0xc9, CpuPNI, NoSuf|ImmExt, { Reg32, Reg32, 0} },
+{"mwait",     2, 0x0f01, 0xc9, CpuPNI|CpuNo64, NoSuf|ImmExt, { Reg32, Reg32, 0} },
+/* Need to ensure only "mwait %rax,%rcx" is accepted.  */
+{"mwait",     2, 0x0f01, 0xc9, CpuPNI|Cpu64, NoSuf|ImmExt|NoRex64, { Reg64, Reg64, 0} },
 
 /* VMX instructions.  */
 {"vmcall",    0, 0x0f01, 0xc1, CpuVMX, NoSuf|ImmExt, { 0, 0, 0} },
--- binutils/opcodes/config.in.pni 2005-04-01 08:54:17.000000000 -0800
+++ binutils/opcodes/config.in 2005-11-17 10:17:56.000000000 -0800
@@ -28,6 +28,10 @@
    don't. */
 #undef HAVE_DECL_BASENAME
 
+/* Define to 1 if you have the declaration of `stpcpy', and to 0 if you don't.
+   */
+#undef HAVE_DECL_STPCPY
+
 /* Define to 1 if you have the `getcwd' function. */
 #undef HAVE_GETCWD
 
@@ -150,6 +154,11 @@
 /* Version number of package */
 #undef VERSION
 
+/* Enable GNU extensions on systems that have them.  */
+#ifndef _GNU_SOURCE
+# undef _GNU_SOURCE
+#endif
+
 /* Define to empty if `const' does not conform to ANSI C. */
 #undef const
 
--- binutils/opcodes/configure.in.pni 2005-10-26 15:03:33.000000000 -0700
+++ binutils/opcodes/configure.in 2005-11-17 10:17:52.000000000 -0800
@@ -59,6 +59,7 @@ AC_EXEEXT
 # host-specific stuff:
 
 AC_PROG_CC
+AC_GNU_SOURCE
 
 ALL_LINGUAS="fr sv tr es da de id pt_BR ro nl fi vi ga"
 CY_GNU_GETTEXT
@@ -72,7 +73,7 @@ AC_PROG_INSTALL
 
 AC_CHECK_HEADERS(string.h strings.h stdlib.h)
 
-AC_CHECK_DECLS(basename)
+AC_CHECK_DECLS([basename, stpcpy])
 
 cgen_maint=no
 cgendir='$(srcdir)/../cgen'
--- binutils/opcodes/configure.pni 2005-11-11 10:48:50.000000000 -0800
+++ binutils/opcodes/configure 2005-11-17 10:17:59.000000000 -0800
@@ -5119,6 +5119,12 @@ ac_link='$CC -o conftest$ac_exeext $CFLA
 ac_compiler_gnu=$ac_cv_c_compiler_gnu
 
 
+cat >>confdefs.h <<\_ACEOF
+#define _GNU_SOURCE 1
+_ACEOF
+
+
+
 ALL_LINGUAS="fr sv tr es da de id pt_BR ro nl fi vi ga"
 if test -n "$ac_tool_prefix"; then
   # Extract the first word of "${ac_tool_prefix}ranlib", so it can be a program name with args.
@@ -8607,6 +8613,76 @@ _ACEOF
 
 
 fi
+echo "$as_me:$LINENO: checking whether stpcpy is declared" >&5
+echo $ECHO_N "checking whether stpcpy is declared... $ECHO_C" >&6
+if test "${ac_cv_have_decl_stpcpy+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+$ac_includes_default
+int
+main ()
+{
+#ifndef stpcpy
+  char *p = (char *) stpcpy;
+#endif
+
+  ;
+  return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext
+if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
+  (eval $ac_compile) 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } &&
+ { ac_try='test -z "$ac_c_werror_flag"
+ || test ! -s conftest.err'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; } &&
+ { ac_try='test -s conftest.$ac_objext'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; }; then
+  ac_cv_have_decl_stpcpy=yes
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ac_cv_have_decl_stpcpy=no
+fi
+rm -f conftest.err conftest.$ac_objext conftest.$ac_ext
+fi
+echo "$as_me:$LINENO: result: $ac_cv_have_decl_stpcpy" >&5
+echo "${ECHO_T}$ac_cv_have_decl_stpcpy" >&6
+if test $ac_cv_have_decl_stpcpy = yes; then
+
+cat >>confdefs.h <<_ACEOF
+#define HAVE_DECL_STPCPY 1
+_ACEOF
+
+
+else
+  cat >>confdefs.h <<_ACEOF
+#define HAVE_DECL_STPCPY 0
+_ACEOF
+
+
+fi
 
 
 
--- binutils/opcodes/i386-dis.c.pni 2005-11-11 10:48:50.000000000 -0800
+++ binutils/opcodes/i386-dis.c 2005-11-17 11:30:56.000000000 -0800
@@ -4412,40 +4412,55 @@ PNI_Fixup (int extrachar ATTRIBUTE_UNUSE
   if (mod == 3 && reg == 1 && rm <= 1)
     {
       /* Override "sidt".  */
-      char *p = obuf + strlen (obuf) - 4;
+      size_t olen = strlen (obuf);
+      char *p = obuf + olen - 4;
+      const char **names = mode_64bit ? names64 : names32;
 
       /* We might have a suffix when disassembling with -Msuffix.  */
       if (*p == 'i')
  --p;
 
+      /* Remove "addr16/addr32" if we aren't in Intel mode.  */
+      if (!intel_syntax
+  && (prefixes & PREFIX_ADDR)
+  && olen >= (4 + 7)
+  && *(p - 1) == ' '
+  && strncmp (p - 7, "addr", 4) == 0
+  && (strncmp (p - 3, "16", 2) == 0
+      || strncmp (p - 3, "32", 2) == 0))
+ p -= 7;
+
       if (rm)
  {
   /* mwait %eax,%ecx  */
   strcpy (p, "mwait");
   if (!intel_syntax)
-    strcpy (op1out, names32[0]);
+    strcpy (op1out, names[0]);
  }
       else
  {
-  /* monitor %eax,%ecx,%edx"  */
+  /* monitor (%eax),%ecx,%edx"  */
   strcpy (p, "monitor");
   if (!intel_syntax)
     {
-      if (!mode_64bit)
- strcpy (op1out, names32[0]);
-      else if (!(prefixes & PREFIX_ADDR))
- strcpy (op1out, names64[0]);
+      const char **op1_names;
+      *op1out = '(';
+      if (!(prefixes & PREFIX_ADDR))
+ op1_names = names;
       else
  {
-  strcpy (op1out, names32[0]);
+  op1_names = mode_64bit ? names32 : names16;
   used_prefixes |= PREFIX_ADDR;
  }
-      strcpy (op3out, names32[2]);
+      p = stpcpy (op1out + 1, op1_names [0]);
+      *p++ = ')';
+      *p++ = '\0';
+      strcpy (op3out, names[2]);
     }
  }
       if (!intel_syntax)
  {
-  strcpy (op2out, names32[1]);
+  strcpy (op2out, names[1]);
   two_source_ops = 1;
  }
 
--- binutils/opcodes/sysdep.h.pni 2005-07-06 08:45:35.000000000 -0700
+++ binutils/opcodes/sysdep.h 2005-11-17 10:10:29.000000000 -0800
@@ -41,3 +41,7 @@
 #include <strings.h>
 #endif
 #endif
+
+#if !HAVE_DECL_STPCPY
+extern char *stpcpy (char *, const char *);
+#endif
Reply | Threaded
Open this post in threaded view
|

Re: PATCH: PR gas/1874: mwait/monitor don't work in 64bit

H.J. Lu-27
On Thu, Nov 17, 2005 at 12:06:13PM -0800, H. J. Lu wrote:

> On Thu, Nov 17, 2005 at 06:05:57PM +0100, Jan Beulich wrote:
> > >>> "H. J. Lu" <[hidden email]> 17.11.05 17:44:06 >>>
> > >On Thu, Nov 17, 2005 at 10:30:05AM +0100, Jan Beulich wrote:
> > >>
> > >> Regarding the patch, I don't think hard-coding the address size
> > >> override for 16-bit operation of monitor is appropriate - under
> > .code16
> > >> this is not going to produce the desired effect (and likewise is
> > the
> > >> opposite 32-bit operation in 16-bit mode then missing the override).
> > The
> > >> base problem here is that monitor's address operand, when
> > explicitly
> > >
> > >The opcode is the same for both 32bit and 64bit modes. The address
> > > size ovverride only changes the size of EAX/RAX. I don't see how
> > >".code16" can be used with it. As for ".code32", it works fine:
> >
> > Why shouldn't BIOS code be using this? This would likely require
> > .code16.
> >
>
> monitor/mwait work in 16bit mode. The address size override prefix can
> be used to change the AX size. This patch support memory as the first
> operand of monitor.
>

I really don't like to use memory operand for monitor. Here is the new
patch without memory operand.


H.J.
----
gas/

2005-11-17  H.J. Lu  <[hidden email]>

        * config/tc-i386.c (match_template): Handle monitor.
        (process_suffix): Likewise.

gas/testsuite/

2005-11-17  H.J. Lu  <[hidden email]>

        PR gas/1874
        * gas/i386/i386.exp: Add x86-64-prescott for 64bit.

        * gas/i386/prescott.s: Test address size override for monitor.
        * gas/i386/prescott.d: Updated.

        * gas/i386/x86-64-prescott.d: New file.
        * gas/i386/x86-64-prescott.s: Likewise.

include/opcode/

2005-11-17  H.J. Lu  <[hidden email]>

        PR gas/1874
        * i386.h (i386_optab): Add 64bit support for monitor and mwait.

opcodes/

2005-11-17  H.J. Lu  <[hidden email]>

        PR gas/1874
        * i386-dis.c (PNI_Fixup): Add 64bit and address size override
        support for monitor and mwait.

--- binutils/gas/config/tc-i386.c.pni 2005-11-11 10:48:52.000000000 -0800
+++ binutils/gas/config/tc-i386.c 2005-11-17 15:00:03.000000000 -0800
@@ -2274,10 +2274,15 @@ match_template ()
   overlap1 = i.types[1] & t->operand_types[1];
   if (!MATCH (overlap0, i.types[0], t->operand_types[0])
       || !MATCH (overlap1, i.types[1], t->operand_types[1])
-      || !CONSISTENT_REGISTER_MATCH (overlap0, i.types[0],
-     t->operand_types[0],
-     overlap1, i.types[1],
-     t->operand_types[1]))
+      /* monitor in SSE3 is a very special case.  The first
+ register and the second register may have differnet
+ sizes.  */
+      || !((t->base_opcode == 0x0f01
+    && t->extension_opcode == 0xc8)
+   || CONSISTENT_REGISTER_MATCH (overlap0, i.types[0],
+ t->operand_types[0],
+ overlap1, i.types[1],
+ t->operand_types[1])))
     {
       /* Check if other direction is valid ...  */
       if ((t->opcode_modifier & (D | FloatD)) == 0)
@@ -2545,12 +2550,24 @@ process_suffix (void)
       /* 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_DOUBLE_MNEM_SUFFIX
-  && !(i.tm.opcode_modifier & (IgnoreSize | FloatMF))
-  && ((i.suffix == LONG_MNEM_SUFFIX) == (flag_code == CODE_16BIT)
-      || (flag_code == CODE_64BIT
-  && (i.tm.opcode_modifier & JumpByte))))
+      if (i.tm.base_opcode == 0x0f01 && i.tm.extension_opcode == 0xc8)
+ {
+  /* monitor in SSE3 is a very special case. The default size
+     of AX is the size of mode. The address size override
+     prefix will change the size of AX.  */
+  if (((flag_code == CODE_16BIT || flag_code == CODE_64BIT)
+       && (i.op->regs[0].reg_type & Reg32))
+      || (flag_code == CODE_32BIT
+  && i.op->regs[0].reg_type & Reg16))
+    if (!add_prefix (ADDR_PREFIX_OPCODE))
+      return 0;
+ }
+      else if (i.suffix != QWORD_MNEM_SUFFIX
+       && i.suffix != LONG_DOUBLE_MNEM_SUFFIX
+       && !(i.tm.opcode_modifier & (IgnoreSize | FloatMF))
+       && ((i.suffix == LONG_MNEM_SUFFIX) == (flag_code == CODE_16BIT)
+   || (flag_code == CODE_64BIT
+       && (i.tm.opcode_modifier & JumpByte))))
  {
   unsigned int prefix = DATA_PREFIX_OPCODE;
 
--- binutils/gas/testsuite/gas/i386/i386.exp.pni 2005-11-11 10:48:53.000000000 -0800
+++ binutils/gas/testsuite/gas/i386/i386.exp 2005-11-15 15:37:50.000000000 -0800
@@ -131,6 +131,7 @@ if [expr ([istarget "i*86-*-*"] || [ista
     run_dump_test "svme64"
     run_dump_test "x86-64-vmx"
     run_dump_test "immed64"
+    run_dump_test "x86-64-prescott"
 
     # For ELF targets verify that @unwind works.
     if { ([istarget "*-*-elf*"] || [istarget "*-*-linux*"]
--- binutils/gas/testsuite/gas/i386/prescott.d.pni 2004-06-23 08:06:57.000000000 -0700
+++ binutils/gas/testsuite/gas/i386/prescott.d 2005-11-17 15:06:52.000000000 -0800
@@ -32,5 +32,6 @@ Disassembly of section .text:
   62: f3 0f 12 dc [ ]*movsldup %xmm4,%xmm3
   66: 0f 01 c9 [ ]*mwait  %eax,%ecx
   69: 0f 01 c9 [ ]*mwait  %eax,%ecx
-  6c: 00 00 [ ]*add    %al,\(%eax\)
+  6c: 67 0f 01 c8 [ ]*monitor %ax,%ecx,%edx
+  70: 67 0f 01 c8 [ ]*monitor %ax,%ecx,%edx
  ...
--- binutils/gas/testsuite/gas/i386/prescott.s.pni 2004-06-23 08:06:58.000000000 -0700
+++ binutils/gas/testsuite/gas/i386/prescott.s 2005-11-17 15:02:25.000000000 -0800
@@ -29,4 +29,7 @@ foo:
  mwait
  mwait %eax,%ecx
 
+ monitor %ax,%ecx,%edx
+ addr16 monitor
+
  .p2align 4,0
--- binutils/gas/testsuite/gas/i386/x86-64-prescott.d.pni 2005-11-15 15:33:49.000000000 -0800
+++ binutils/gas/testsuite/gas/i386/x86-64-prescott.d 2005-11-17 15:02:46.000000000 -0800
@@ -0,0 +1,37 @@
+#objdump: -dw
+#name: x86-64 prescott
+
+.*: +file format .*
+
+Disassembly of section .text:
+
+0+000 <foo>:
+   0: 66 0f d0 01 [ ]*addsubpd \(%rcx\),%xmm0
+   4: 66 0f d0 ca [ ]*addsubpd %xmm2,%xmm1
+   8: f2 0f d0 13 [ ]*addsubps \(%rbx\),%xmm2
+   c: f2 0f d0 dc [ ]*addsubps %xmm4,%xmm3
+  10: df 88 90 90 90 90 [ ]*fisttp 0xffffffff90909090\(%rax\)
+  16: db 88 90 90 90 90 [ ]*fisttpl 0xffffffff90909090\(%rax\)
+  1c: dd 88 90 90 90 90 [ ]*fisttpll 0xffffffff90909090\(%rax\)
+  22: 66 0f 7c 65 00 [ ]*haddpd 0x0\(%rbp\),%xmm4
+  27: 66 0f 7c ee [ ]*haddpd %xmm6,%xmm5
+  2b: f2 0f 7c 37 [ ]*haddps \(%rdi\),%xmm6
+  2f: f2 0f 7c f8 [ ]*haddps %xmm0,%xmm7
+  33: 66 0f 7d c1 [ ]*hsubpd %xmm1,%xmm0
+  37: 66 0f 7d 0a [ ]*hsubpd \(%rdx\),%xmm1
+  3b: f2 0f 7d d2 [ ]*hsubps %xmm2,%xmm2
+  3f: f2 0f 7d 1c 24 [ ]*hsubps \(%rsp\),%xmm3
+  44: f2 0f f0 2e [ ]*lddqu  \(%rsi\),%xmm5
+  48: 0f 01 c8 [ ]*monitor %rax,%rcx,%rdx
+  4b: 0f 01 c8 [ ]*monitor %rax,%rcx,%rdx
+  4e: f2 0f 12 f7 [ ]*movddup %xmm7,%xmm6
+  52: f2 0f 12 38 [ ]*movddup \(%rax\),%xmm7
+  56: f3 0f 16 01 [ ]*movshdup \(%rcx\),%xmm0
+  5a: f3 0f 16 ca [ ]*movshdup %xmm2,%xmm1
+  5e: f3 0f 12 13 [ ]*movsldup \(%rbx\),%xmm2
+  62: f3 0f 12 dc [ ]*movsldup %xmm4,%xmm3
+  66: 0f 01 c9 [ ]*mwait  %rax,%rcx
+  69: 0f 01 c9 [ ]*mwait  %rax,%rcx
+  6c: 67 0f 01 c8 [ ]*monitor %eax,%rcx,%rdx
+  70: 67 0f 01 c8 [ ]*monitor %eax,%rcx,%rdx
+ ...
--- binutils/gas/testsuite/gas/i386/x86-64-prescott.s.pni 2005-11-15 15:33:47.000000000 -0800
+++ binutils/gas/testsuite/gas/i386/x86-64-prescott.s 2005-11-17 15:03:00.000000000 -0800
@@ -0,0 +1,35 @@
+#Prescott New Instructions
+
+ .text
+foo:
+ addsubpd (%rcx),%xmm0
+ addsubpd %xmm2,%xmm1
+ addsubps (%rbx),%xmm2
+ addsubps %xmm4,%xmm3
+ fisttp 0x90909090(%rax)
+ fisttpl 0x90909090(%rax)
+ fisttpll 0x90909090(%rax)
+ haddpd 0x0(%rbp),%xmm4
+ haddpd %xmm6,%xmm5
+ haddps (%rdi),%xmm6
+ haddps %xmm0,%xmm7
+ hsubpd %xmm1,%xmm0
+ hsubpd (%rdx),%xmm1
+ hsubps %xmm2,%xmm2
+ hsubps (%rsp,1),%xmm3
+ lddqu (%rsi),%xmm5
+ monitor
+ monitor %rax,%rcx,%rdx
+ movddup %xmm7,%xmm6
+ movddup (%rax),%xmm7
+ movshdup (%rcx),%xmm0
+ movshdup %xmm2,%xmm1
+ movsldup (%rbx),%xmm2
+ movsldup %xmm4,%xmm3
+ mwait
+ mwait %rax,%rcx
+
+ monitor %eax,%rcx,%rdx
+ addr32 monitor
+
+ .p2align 4,0
--- binutils/include/opcode/i386.h.pni 2005-07-27 08:41:15.000000000 -0700
+++ binutils/include/opcode/i386.h 2005-11-17 15:09:47.000000000 -0800
@@ -1346,14 +1346,24 @@ static const template i386_optab[] =
 {"hsubps",    2, 0xf20f7d,  X, CpuPNI, NoSuf|IgnoreSize|Modrm, { RegXMM|LLongMem, RegXMM, 0 } },
 {"lddqu",     2, 0xf20ff0,  X, CpuPNI, NoSuf|IgnoreSize|Modrm, { LLongMem, RegXMM, 0 } },
 {"monitor",   0, 0x0f01, 0xc8, CpuPNI, NoSuf|ImmExt, { 0, 0, 0} },
-/* Need to ensure only "monitor %eax,%ecx,%edx" is accepted. */
-{"monitor",   3, 0x0f01, 0xc8, CpuPNI, NoSuf|ImmExt, { Reg32, Reg32, Reg32} },
+/* monitor is very special. CX and DX are always 64bits with zero upper
+   32bits in 64bit mode, and 32bits in 16bit and 32bit modes. The
+   address size override prefix can be used to overrride the AX size in
+   all modes.  */
+/* Need to ensure only "monitor %eax/%ax,%ecx,%edx" is accepted. */
+{"monitor",   3, 0x0f01, 0xc8, CpuPNI|CpuNo64, NoSuf|ImmExt, { Reg16|Reg32, Reg32, Reg32 } },
+/* Need to ensure only "monitor %rax/%eax,%rcx,%rdx" is accepted. */
+{"monitor",   3, 0x0f01, 0xc8, CpuPNI|Cpu64, NoSuf|ImmExt|NoRex64, { Reg32|Reg64, Reg64, Reg64 } },
 {"movddup",   2, 0xf20f12,  X, CpuPNI, NoSuf|IgnoreSize|Modrm, { RegXMM|LLongMem, RegXMM, 0 } },
 {"movshdup",  2, 0xf30f16,  X, CpuPNI, NoSuf|IgnoreSize|Modrm, { RegXMM|LLongMem, RegXMM, 0 } },
 {"movsldup",  2, 0xf30f12,  X, CpuPNI, NoSuf|IgnoreSize|Modrm, { RegXMM|LLongMem, RegXMM, 0 } },
 {"mwait",     0, 0x0f01, 0xc9, CpuPNI, NoSuf|ImmExt, { 0, 0, 0} },
+/* mwait is very special. AX and CX are always 64bits with zero upper
+   32bits in 64bit mode, and 32bits in 16bit and 32bit modes.  */
 /* Need to ensure only "mwait %eax,%ecx" is accepted.  */
-{"mwait",     2, 0x0f01, 0xc9, CpuPNI, NoSuf|ImmExt, { Reg32, Reg32, 0} },
+{"mwait",     2, 0x0f01, 0xc9, CpuPNI|CpuNo64, NoSuf|ImmExt, { Reg32, Reg32, 0} },
+/* Need to ensure only "mwait %rax,%rcx" is accepted.  */
+{"mwait",     2, 0x0f01, 0xc9, CpuPNI|Cpu64, NoSuf|ImmExt|NoRex64, { Reg64, Reg64, 0} },
 
 /* VMX instructions.  */
 {"vmcall",    0, 0x0f01, 0xc1, CpuVMX, NoSuf|ImmExt, { 0, 0, 0} },
--- binutils/opcodes/i386-dis.c.pni 2005-11-11 10:48:50.000000000 -0800
+++ binutils/opcodes/i386-dis.c 2005-11-17 14:52:31.000000000 -0800
@@ -4412,18 +4412,30 @@ PNI_Fixup (int extrachar ATTRIBUTE_UNUSE
   if (mod == 3 && reg == 1 && rm <= 1)
     {
       /* Override "sidt".  */
-      char *p = obuf + strlen (obuf) - 4;
+      size_t olen = strlen (obuf);
+      char *p = obuf + olen - 4;
+      const char **names = mode_64bit ? names64 : names32;
 
       /* We might have a suffix when disassembling with -Msuffix.  */
       if (*p == 'i')
  --p;
 
+      /* Remove "addr16/addr32" if we aren't in Intel mode.  */
+      if (!intel_syntax
+  && (prefixes & PREFIX_ADDR)
+  && olen >= (4 + 7)
+  && *(p - 1) == ' '
+  && strncmp (p - 7, "addr", 4) == 0
+  && (strncmp (p - 3, "16", 2) == 0
+      || strncmp (p - 3, "32", 2) == 0))
+ p -= 7;
+
       if (rm)
  {
   /* mwait %eax,%ecx  */
   strcpy (p, "mwait");
   if (!intel_syntax)
-    strcpy (op1out, names32[0]);
+    strcpy (op1out, names[0]);
  }
       else
  {
@@ -4431,21 +4443,21 @@ PNI_Fixup (int extrachar ATTRIBUTE_UNUSE
   strcpy (p, "monitor");
   if (!intel_syntax)
     {
-      if (!mode_64bit)
- strcpy (op1out, names32[0]);
-      else if (!(prefixes & PREFIX_ADDR))
- strcpy (op1out, names64[0]);
+      const char **op1_names;
+      if (!(prefixes & PREFIX_ADDR))
+ op1_names = names;
       else
  {
-  strcpy (op1out, names32[0]);
+  op1_names = mode_64bit ? names32 : names16;
   used_prefixes |= PREFIX_ADDR;
  }
-      strcpy (op3out, names32[2]);
+      strcpy (op1out, op1_names[0]);
+      strcpy (op3out, names[2]);
     }
  }
       if (!intel_syntax)
  {
-  strcpy (op2out, names32[1]);
+  strcpy (op2out, names[1]);
   two_source_ops = 1;
  }
 
Reply | Threaded
Open this post in threaded view
|

Re: PATCH: PR gas/1874: mwait/monitor don't work in 64bit

Jan Beulich
>I really don't like to use memory operand for monitor. Here is the new
>patch without memory operand.

Any particular reason for that? But I don't really mind...

>+  if (((flag_code == CODE_16BIT || flag_code == CODE_64BIT)
>+       && (i.op->regs[0].reg_type & Reg32))
>+      || (flag_code == CODE_32BIT
>+  && i.op->regs[0].reg_type & Reg16))

While I recognize this is partly a stylistic thing, I would see this
more readable if simplified:

          if (i.op->regs[0].reg_type & (flag_code != CODE_32BIT ? Reg32
: Reg16))

>+      /* Remove "addr16/addr32" if we aren't in Intel mode.  */
>+      if (!intel_syntax
>+  && (prefixes & PREFIX_ADDR)
>+  && olen >= (4 + 7)
>+  && *(p - 1) == ' '
>+  && strncmp (p - 7, "addr", 4) == 0
>+  && (strncmp (p - 3, "16", 2) == 0
>+      || strncmp (p - 3, "32", 2) == 0))
>+ p -= 7;
>+

Oh, I see, I asked for a thing that needs general cleanup. I was mixing
up the behaviors of PREFIX_ADDR and PREFIX_DATA. It really should be
opcode-independent code that deals with suppressing this. I withdraw my
request to suppress addrXX, but I leave it up to you if you want to keep
this piece.

Jan

Jan
Reply | Threaded
Open this post in threaded view
|

Re: PATCH: PR gas/1874: mwait/monitor don't work in 64bit

H.J. Lu-27
On Fri, Nov 18, 2005 at 09:06:17AM +0100, Jan Beulich wrote:

> >I really don't like to use memory operand for monitor. Here is the new
> >patch without memory operand.
>
> Any particular reason for that? But I don't really mind...
>
> >+  if (((flag_code == CODE_16BIT || flag_code == CODE_64BIT)
> >+       && (i.op->regs[0].reg_type & Reg32))
> >+      || (flag_code == CODE_32BIT
> >+  && i.op->regs[0].reg_type & Reg16))
>
> While I recognize this is partly a stylistic thing, I would see this
> more readable if simplified:
>
>  if (i.op->regs[0].reg_type & (flag_code != CODE_32BIT ? Reg32
> : Reg16))

Ok.

>
> >+      /* Remove "addr16/addr32" if we aren't in Intel mode.  */
> >+      if (!intel_syntax
> >+  && (prefixes & PREFIX_ADDR)
> >+  && olen >= (4 + 7)
> >+  && *(p - 1) == ' '
> >+  && strncmp (p - 7, "addr", 4) == 0
> >+  && (strncmp (p - 3, "16", 2) == 0
> >+      || strncmp (p - 3, "32", 2) == 0))
> >+ p -= 7;
> >+
>
> Oh, I see, I asked for a thing that needs general cleanup. I was mixing
> up the behaviors of PREFIX_ADDR and PREFIX_DATA. It really should be
> opcode-independent code that deals with suppressing this. I withdraw my
> request to suppress addrXX, but I leave it up to you if you want to keep
> this piece.
>

Here is the updated patch. I also changed "objdump -d -Mi8086". I think
there is a bigger issue for -Mi8086:

[hjl@gnu-13 monitor]$ ./objdump -d -Mintel:i8086 32.o

32.o:     file format elf32-i386

Disassembly of section .text:

00000000 <.text>:
   0:   0f 01 c8                monitor
   3:   67 0f 01 c8             addr16 monitor

It should be addr32, not addr16. I think the mode_16bit may help fix
it.

BTW, I will take a vacation until Dec. 3. If I don't check in my patch
today, I will do it after 2 weeks.


H.J.
----
gas/

2005-11-17  H.J. Lu  <[hidden email]>

        * config/tc-i386.c (match_template): Handle monitor.
        (process_suffix): Likewise.

gas/testsuite/

2005-11-17  H.J. Lu  <[hidden email]>

        PR gas/1874
        * gas/i386/i386.exp: Add x86-64-prescott for 64bit.

        * gas/i386/prescott.s: Test address size override for monitor.
        * gas/i386/prescott.d: Updated.

        * gas/i386/x86-64-prescott.d: New file.
        * gas/i386/x86-64-prescott.s: Likewise.

include/opcode/

2005-11-17  H.J. Lu  <[hidden email]>

        PR gas/1874
        * i386.h (i386_optab): Add 64bit support for monitor and mwait.

opcodes/

2005-11-17  H.J. Lu  <[hidden email]>

        PR gas/1874
        * i386-dis.c (mode_16bit): New.
        (print_insn): Set mode_16bit to 1 for "i8086".
        (PNI_Fixup): Add 64bit and address size override
        support for monitor and mwait.

--- binutils/gas/config/tc-i386.c.pni 2005-11-11 10:48:52.000000000 -0800
+++ binutils/gas/config/tc-i386.c 2005-11-18 08:51:59.000000000 -0800
@@ -2274,10 +2274,15 @@ match_template ()
   overlap1 = i.types[1] & t->operand_types[1];
   if (!MATCH (overlap0, i.types[0], t->operand_types[0])
       || !MATCH (overlap1, i.types[1], t->operand_types[1])
-      || !CONSISTENT_REGISTER_MATCH (overlap0, i.types[0],
-     t->operand_types[0],
-     overlap1, i.types[1],
-     t->operand_types[1]))
+      /* monitor in SSE3 is a very special case.  The first
+ register and the second register may have differnet
+ sizes.  */
+      || !((t->base_opcode == 0x0f01
+    && t->extension_opcode == 0xc8)
+   || CONSISTENT_REGISTER_MATCH (overlap0, i.types[0],
+ t->operand_types[0],
+ overlap1, i.types[1],
+ t->operand_types[1])))
     {
       /* Check if other direction is valid ...  */
       if ((t->opcode_modifier & (D | FloatD)) == 0)
@@ -2545,12 +2550,22 @@ process_suffix (void)
       /* 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_DOUBLE_MNEM_SUFFIX
-  && !(i.tm.opcode_modifier & (IgnoreSize | FloatMF))
-  && ((i.suffix == LONG_MNEM_SUFFIX) == (flag_code == CODE_16BIT)
-      || (flag_code == CODE_64BIT
-  && (i.tm.opcode_modifier & JumpByte))))
+      if (i.tm.base_opcode == 0x0f01 && i.tm.extension_opcode == 0xc8)
+ {
+  /* monitor in SSE3 is a very special case. The default size
+     of AX is the size of mode. The address size override
+     prefix will change the size of AX.  */
+  if (i.op->regs[0].reg_type &
+      (flag_code == CODE_32BIT ? Reg16 : Reg32))
+    if (!add_prefix (ADDR_PREFIX_OPCODE))
+      return 0;
+ }
+      else if (i.suffix != QWORD_MNEM_SUFFIX
+       && i.suffix != LONG_DOUBLE_MNEM_SUFFIX
+       && !(i.tm.opcode_modifier & (IgnoreSize | FloatMF))
+       && ((i.suffix == LONG_MNEM_SUFFIX) == (flag_code == CODE_16BIT)
+   || (flag_code == CODE_64BIT
+       && (i.tm.opcode_modifier & JumpByte))))
  {
   unsigned int prefix = DATA_PREFIX_OPCODE;
 
--- binutils/gas/testsuite/gas/i386/i386.exp.pni 2005-11-11 10:48:53.000000000 -0800
+++ binutils/gas/testsuite/gas/i386/i386.exp 2005-11-15 15:37:50.000000000 -0800
@@ -131,6 +131,7 @@ if [expr ([istarget "i*86-*-*"] || [ista
     run_dump_test "svme64"
     run_dump_test "x86-64-vmx"
     run_dump_test "immed64"
+    run_dump_test "x86-64-prescott"
 
     # For ELF targets verify that @unwind works.
     if { ([istarget "*-*-elf*"] || [istarget "*-*-linux*"]
--- binutils/gas/testsuite/gas/i386/prescott.d.pni 2004-06-23 08:06:57.000000000 -0700
+++ binutils/gas/testsuite/gas/i386/prescott.d 2005-11-17 15:06:52.000000000 -0800
@@ -32,5 +32,6 @@ Disassembly of section .text:
   62: f3 0f 12 dc [ ]*movsldup %xmm4,%xmm3
   66: 0f 01 c9 [ ]*mwait  %eax,%ecx
   69: 0f 01 c9 [ ]*mwait  %eax,%ecx
-  6c: 00 00 [ ]*add    %al,\(%eax\)
+  6c: 67 0f 01 c8 [ ]*monitor %ax,%ecx,%edx
+  70: 67 0f 01 c8 [ ]*monitor %ax,%ecx,%edx
  ...
--- binutils/gas/testsuite/gas/i386/prescott.s.pni 2004-06-23 08:06:58.000000000 -0700
+++ binutils/gas/testsuite/gas/i386/prescott.s 2005-11-17 15:02:25.000000000 -0800
@@ -29,4 +29,7 @@ foo:
  mwait
  mwait %eax,%ecx
 
+ monitor %ax,%ecx,%edx
+ addr16 monitor
+
  .p2align 4,0
--- binutils/gas/testsuite/gas/i386/x86-64-prescott.d.pni 2005-11-15 15:33:49.000000000 -0800
+++ binutils/gas/testsuite/gas/i386/x86-64-prescott.d 2005-11-17 15:02:46.000000000 -0800
@@ -0,0 +1,37 @@
+#objdump: -dw
+#name: x86-64 prescott
+
+.*: +file format .*
+
+Disassembly of section .text:
+
+0+000 <foo>:
+   0: 66 0f d0 01 [ ]*addsubpd \(%rcx\),%xmm0
+   4: 66 0f d0 ca [ ]*addsubpd %xmm2,%xmm1
+   8: f2 0f d0 13 [ ]*addsubps \(%rbx\),%xmm2
+   c: f2 0f d0 dc [ ]*addsubps %xmm4,%xmm3
+  10: df 88 90 90 90 90 [ ]*fisttp 0xffffffff90909090\(%rax\)
+  16: db 88 90 90 90 90 [ ]*fisttpl 0xffffffff90909090\(%rax\)
+  1c: dd 88 90 90 90 90 [ ]*fisttpll 0xffffffff90909090\(%rax\)
+  22: 66 0f 7c 65 00 [ ]*haddpd 0x0\(%rbp\),%xmm4
+  27: 66 0f 7c ee [ ]*haddpd %xmm6,%xmm5
+  2b: f2 0f 7c 37 [ ]*haddps \(%rdi\),%xmm6
+  2f: f2 0f 7c f8 [ ]*haddps %xmm0,%xmm7
+  33: 66 0f 7d c1 [ ]*hsubpd %xmm1,%xmm0
+  37: 66 0f 7d 0a [ ]*hsubpd \(%rdx\),%xmm1
+  3b: f2 0f 7d d2 [ ]*hsubps %xmm2,%xmm2
+  3f: f2 0f 7d 1c 24 [ ]*hsubps \(%rsp\),%xmm3
+  44: f2 0f f0 2e [ ]*lddqu  \(%rsi\),%xmm5
+  48: 0f 01 c8 [ ]*monitor %rax,%rcx,%rdx
+  4b: 0f 01 c8 [ ]*monitor %rax,%rcx,%rdx
+  4e: f2 0f 12 f7 [ ]*movddup %xmm7,%xmm6
+  52: f2 0f 12 38 [ ]*movddup \(%rax\),%xmm7
+  56: f3 0f 16 01 [ ]*movshdup \(%rcx\),%xmm0
+  5a: f3 0f 16 ca [ ]*movshdup %xmm2,%xmm1
+  5e: f3 0f 12 13 [ ]*movsldup \(%rbx\),%xmm2
+  62: f3 0f 12 dc [ ]*movsldup %xmm4,%xmm3
+  66: 0f 01 c9 [ ]*mwait  %rax,%rcx
+  69: 0f 01 c9 [ ]*mwait  %rax,%rcx
+  6c: 67 0f 01 c8 [ ]*monitor %eax,%rcx,%rdx
+  70: 67 0f 01 c8 [ ]*monitor %eax,%rcx,%rdx
+ ...
--- binutils/gas/testsuite/gas/i386/x86-64-prescott.s.pni 2005-11-15 15:33:47.000000000 -0800
+++ binutils/gas/testsuite/gas/i386/x86-64-prescott.s 2005-11-17 15:03:00.000000000 -0800
@@ -0,0 +1,35 @@
+#Prescott New Instructions
+
+ .text
+foo:
+ addsubpd (%rcx),%xmm0
+ addsubpd %xmm2,%xmm1
+ addsubps (%rbx),%xmm2
+ addsubps %xmm4,%xmm3
+ fisttp 0x90909090(%rax)
+ fisttpl 0x90909090(%rax)
+ fisttpll 0x90909090(%rax)
+ haddpd 0x0(%rbp),%xmm4
+ haddpd %xmm6,%xmm5
+ haddps (%rdi),%xmm6
+ haddps %xmm0,%xmm7
+ hsubpd %xmm1,%xmm0
+ hsubpd (%rdx),%xmm1
+ hsubps %xmm2,%xmm2
+ hsubps (%rsp,1),%xmm3
+ lddqu (%rsi),%xmm5
+ monitor
+ monitor %rax,%rcx,%rdx
+ movddup %xmm7,%xmm6
+ movddup (%rax),%xmm7
+ movshdup (%rcx),%xmm0
+ movshdup %xmm2,%xmm1
+ movsldup (%rbx),%xmm2
+ movsldup %xmm4,%xmm3
+ mwait
+ mwait %rax,%rcx
+
+ monitor %eax,%rcx,%rdx
+ addr32 monitor
+
+ .p2align 4,0
--- binutils/include/opcode/i386.h.pni 2005-07-27 08:41:15.000000000 -0700
+++ binutils/include/opcode/i386.h 2005-11-17 15:09:47.000000000 -0800
@@ -1346,14 +1346,24 @@ static const template i386_optab[] =
 {"hsubps",    2, 0xf20f7d,  X, CpuPNI, NoSuf|IgnoreSize|Modrm, { RegXMM|LLongMem, RegXMM, 0 } },
 {"lddqu",     2, 0xf20ff0,  X, CpuPNI, NoSuf|IgnoreSize|Modrm, { LLongMem, RegXMM, 0 } },
 {"monitor",   0, 0x0f01, 0xc8, CpuPNI, NoSuf|ImmExt, { 0, 0, 0} },
-/* Need to ensure only "monitor %eax,%ecx,%edx" is accepted. */
-{"monitor",   3, 0x0f01, 0xc8, CpuPNI, NoSuf|ImmExt, { Reg32, Reg32, Reg32} },
+/* monitor is very special. CX and DX are always 64bits with zero upper
+   32bits in 64bit mode, and 32bits in 16bit and 32bit modes. The
+   address size override prefix can be used to overrride the AX size in
+   all modes.  */
+/* Need to ensure only "monitor %eax/%ax,%ecx,%edx" is accepted. */
+{"monitor",   3, 0x0f01, 0xc8, CpuPNI|CpuNo64, NoSuf|ImmExt, { Reg16|Reg32, Reg32, Reg32 } },
+/* Need to ensure only "monitor %rax/%eax,%rcx,%rdx" is accepted. */
+{"monitor",   3, 0x0f01, 0xc8, CpuPNI|Cpu64, NoSuf|ImmExt|NoRex64, { Reg32|Reg64, Reg64, Reg64 } },
 {"movddup",   2, 0xf20f12,  X, CpuPNI, NoSuf|IgnoreSize|Modrm, { RegXMM|LLongMem, RegXMM, 0 } },
 {"movshdup",  2, 0xf30f16,  X, CpuPNI, NoSuf|IgnoreSize|Modrm, { RegXMM|LLongMem, RegXMM, 0 } },
 {"movsldup",  2, 0xf30f12,  X, CpuPNI, NoSuf|IgnoreSize|Modrm, { RegXMM|LLongMem, RegXMM, 0 } },
 {"mwait",     0, 0x0f01, 0xc9, CpuPNI, NoSuf|ImmExt, { 0, 0, 0} },
+/* mwait is very special. AX and CX are always 64bits with zero upper
+   32bits in 64bit mode, and 32bits in 16bit and 32bit modes.  */
 /* Need to ensure only "mwait %eax,%ecx" is accepted.  */
-{"mwait",     2, 0x0f01, 0xc9, CpuPNI, NoSuf|ImmExt, { Reg32, Reg32, 0} },
+{"mwait",     2, 0x0f01, 0xc9, CpuPNI|CpuNo64, NoSuf|ImmExt, { Reg32, Reg32, 0} },
+/* Need to ensure only "mwait %rax,%rcx" is accepted.  */
+{"mwait",     2, 0x0f01, 0xc9, CpuPNI|Cpu64, NoSuf|ImmExt|NoRex64, { Reg64, Reg64, 0} },
 
 /* VMX instructions.  */
 {"vmcall",    0, 0x0f01, 0xc1, CpuVMX, NoSuf|ImmExt, { 0, 0, 0} },
--- binutils/opcodes/i386-dis.c.pni 2005-11-11 10:48:50.000000000 -0800
+++ binutils/opcodes/i386-dis.c 2005-11-18 09:12:15.000000000 -0800
@@ -118,6 +118,9 @@ struct dis_private {
 /* Set to 1 for 64bit mode disassembly.  */
 static int mode_64bit;
 
+/* Set to 1 for 16bit mode disassembly.  */
+static int mode_16bit;
+
 /* Flags for the prefixes for the current instruction.  See below.  */
 static int prefixes;
 
@@ -1972,6 +1975,7 @@ print_insn (bfd_vma pc, disassemble_info
 
   mode_64bit = (info->mach == bfd_mach_x86_64_intel_syntax
  || info->mach == bfd_mach_x86_64);
+  mode_16bit = 0;
 
   if (intel_syntax == (char) -1)
     intel_syntax = (info->mach == bfd_mach_i386_i386_intel_syntax
@@ -1992,16 +1996,19 @@ print_insn (bfd_vma pc, disassemble_info
       if (strncmp (p, "x86-64", 6) == 0)
  {
   mode_64bit = 1;
+  mode_16bit = 0;
   priv.orig_sizeflag = AFLAG | DFLAG;
  }
       else if (strncmp (p, "i386", 4) == 0)
  {
   mode_64bit = 0;
+  mode_16bit = 0;
   priv.orig_sizeflag = AFLAG | DFLAG;
  }
       else if (strncmp (p, "i8086", 5) == 0)
  {
   mode_64bit = 0;
+  mode_16bit = 1;
   priv.orig_sizeflag = 0;
  }
       else if (strncmp (p, "intel", 5) == 0)
@@ -4412,18 +4419,30 @@ PNI_Fixup (int extrachar ATTRIBUTE_UNUSE
   if (mod == 3 && reg == 1 && rm <= 1)
     {
       /* Override "sidt".  */
-      char *p = obuf + strlen (obuf) - 4;
+      size_t olen = strlen (obuf);
+      char *p = obuf + olen - 4;
+      const char **names = mode_64bit ? names64 : names32;
 
       /* We might have a suffix when disassembling with -Msuffix.  */
       if (*p == 'i')
  --p;
 
+      /* Remove "addr16/addr32" if we aren't in Intel mode.  */
+      if (!intel_syntax
+  && (prefixes & PREFIX_ADDR)
+  && olen >= (4 + 7)
+  && *(p - 1) == ' '
+  && strncmp (p - 7, "addr", 4) == 0
+  && (strncmp (p - 3, "16", 2) == 0
+      || strncmp (p - 3, "32", 2) == 0))
+ p -= 7;
+
       if (rm)
  {
   /* mwait %eax,%ecx  */
   strcpy (p, "mwait");
   if (!intel_syntax)
-    strcpy (op1out, names32[0]);
+    strcpy (op1out, names[0]);
  }
       else
  {
@@ -4431,21 +4450,22 @@ PNI_Fixup (int extrachar ATTRIBUTE_UNUSE
   strcpy (p, "monitor");
   if (!intel_syntax)
     {
-      if (!mode_64bit)
- strcpy (op1out, names32[0]);
-      else if (!(prefixes & PREFIX_ADDR))
- strcpy (op1out, names64[0]);
+      const char **op1_names;
+      if (!(prefixes & PREFIX_ADDR))
+ op1_names = mode_16bit ? names16 : names;
       else
  {
-  strcpy (op1out, names32[0]);
+  op1_names = ((mode_64bit || mode_16bit)
+       ? names32 : names16);
   used_prefixes |= PREFIX_ADDR;
  }
-      strcpy (op3out, names32[2]);
+      strcpy (op1out, op1_names[0]);
+      strcpy (op3out, names[2]);
     }
  }
       if (!intel_syntax)
  {
-  strcpy (op2out, names32[1]);
+  strcpy (op2out, names[1]);
   two_source_ops = 1;
  }
 
Reply | Threaded
Open this post in threaded view
|

Re: PATCH: PR gas/1874: mwait/monitor don't work in 64bit

H.J. Lu-27
On Fri, Nov 18, 2005 at 09:25:27AM -0800, H. J. Lu wrote:

>
> Here is the updated patch. I also changed "objdump -d -Mi8086". I think
> there is a bigger issue for -Mi8086:
>
> [hjl@gnu-13 monitor]$ ./objdump -d -Mintel:i8086 32.o
>
> 32.o:     file format elf32-i386
>
> Disassembly of section .text:
>
> 00000000 <.text>:
>    0:   0f 01 c8                monitor
>    3:   67 0f 01 c8             addr16 monitor
>
> It should be addr32, not addr16. I think the mode_16bit may help fix
> it.
>
> BTW, I will take a vacation until Dec. 3. If I don't check in my patch
> today, I will do it after 2 weeks.
>

I will check in this patch shortly. Someone can fix the 16bit support
when the new address_mode variable.


H.J.
---
gas/

2005-12-05  H.J. Lu  <[hidden email]>

        PR gas/1874
        * config/tc-i386.c (match_template): Handle monitor.
        (process_suffix): Likewise.

gas/testsuite/

2005-12-05  H.J. Lu  <[hidden email]>

        PR gas/1874
        * gas/i386/i386.exp: Add x86-64-prescott for 64bit.

        * gas/i386/prescott.s: Test address size override for monitor.
        * gas/i386/prescott.d: Updated.

        * gas/i386/x86-64-prescott.d: New file.
        * gas/i386/x86-64-prescott.s: Likewise.

include/opcode/

2005-12-05  H.J. Lu  <[hidden email]>

        PR gas/1874
        * i386.h (i386_optab): Add 64bit support for monitor and mwait.

opcodes/

2005-11-17  H.J. Lu  <[hidden email]>

        PR gas/1874
        * i386-dis.c (address_mode): New enum type.
        (address_mode): New variable.
        (mode_64bit): Removed.
        (ckprefix): Updated to check address_mode instead of mode_64bit.
        (prefix_name): Likewise.
        (print_insn): Likewise.
        (putop): Likewise.
        (print_operand_value): Likewise.
        (intel_operand_size): Likewise.
        (OP_E): Likewise.
        (OP_G): Likewise.
        (set_op): Likewise.
        (OP_REG): Likewise.
        (OP_I): Likewise.
        (OP_I64): Likewise.
        (OP_OFF): Likewise.
        (OP_OFF64): Likewise.
        (ptr_reg): Likewise.
        (OP_C): Likewise.
        (SVME_Fixup): Likewise.
        (print_insn): Set address_mode.
        (PNI_Fixup): Add 64bit and address size override support for
        monitor and mwait.

--- binutils/gas/config/tc-i386.c.pni 2005-12-05 14:28:42.000000000 -0800
+++ binutils/gas/config/tc-i386.c 2005-12-05 14:29:59.000000000 -0800
@@ -2275,10 +2275,15 @@ match_template ()
   overlap1 = i.types[1] & t->operand_types[1];
   if (!MATCH (overlap0, i.types[0], t->operand_types[0])
       || !MATCH (overlap1, i.types[1], t->operand_types[1])
-      || !CONSISTENT_REGISTER_MATCH (overlap0, i.types[0],
-     t->operand_types[0],
-     overlap1, i.types[1],
-     t->operand_types[1]))
+      /* monitor in SSE3 is a very special case.  The first
+ register and the second register may have differnet
+ sizes.  */
+      || !((t->base_opcode == 0x0f01
+    && t->extension_opcode == 0xc8)
+   || CONSISTENT_REGISTER_MATCH (overlap0, i.types[0],
+ t->operand_types[0],
+ overlap1, i.types[1],
+ t->operand_types[1])))
     {
       /* Check if other direction is valid ...  */
       if ((t->opcode_modifier & (D | FloatD)) == 0)
@@ -2546,12 +2551,22 @@ process_suffix (void)
       /* 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_DOUBLE_MNEM_SUFFIX
-  && !(i.tm.opcode_modifier & (IgnoreSize | FloatMF))
-  && ((i.suffix == LONG_MNEM_SUFFIX) == (flag_code == CODE_16BIT)
-      || (flag_code == CODE_64BIT
-  && (i.tm.opcode_modifier & JumpByte))))
+      if (i.tm.base_opcode == 0x0f01 && i.tm.extension_opcode == 0xc8)
+ {
+  /* monitor in SSE3 is a very special case. The default size
+     of AX is the size of mode. The address size override
+     prefix will change the size of AX.  */
+  if (i.op->regs[0].reg_type &
+      (flag_code == CODE_32BIT ? Reg16 : Reg32))
+    if (!add_prefix (ADDR_PREFIX_OPCODE))
+      return 0;
+ }
+      else if (i.suffix != QWORD_MNEM_SUFFIX
+       && i.suffix != LONG_DOUBLE_MNEM_SUFFIX
+       && !(i.tm.opcode_modifier & (IgnoreSize | FloatMF))
+       && ((i.suffix == LONG_MNEM_SUFFIX) == (flag_code == CODE_16BIT)
+   || (flag_code == CODE_64BIT
+       && (i.tm.opcode_modifier & JumpByte))))
  {
   unsigned int prefix = DATA_PREFIX_OPCODE;
 
--- binutils/gas/testsuite/gas/i386/i386.exp.pni 2005-11-11 10:48:53.000000000 -0800
+++ binutils/gas/testsuite/gas/i386/i386.exp 2005-12-05 14:29:59.000000000 -0800
@@ -131,6 +131,7 @@ if [expr ([istarget "i*86-*-*"] || [ista
     run_dump_test "svme64"
     run_dump_test "x86-64-vmx"
     run_dump_test "immed64"
+    run_dump_test "x86-64-prescott"
 
     # For ELF targets verify that @unwind works.
     if { ([istarget "*-*-elf*"] || [istarget "*-*-linux*"]
--- binutils/gas/testsuite/gas/i386/prescott.d.pni 2004-06-23 08:06:57.000000000 -0700
+++ binutils/gas/testsuite/gas/i386/prescott.d 2005-12-05 14:29:59.000000000 -0800
@@ -32,5 +32,6 @@ Disassembly of section .text:
   62: f3 0f 12 dc [ ]*movsldup %xmm4,%xmm3
   66: 0f 01 c9 [ ]*mwait  %eax,%ecx
   69: 0f 01 c9 [ ]*mwait  %eax,%ecx
-  6c: 00 00 [ ]*add    %al,\(%eax\)
+  6c: 67 0f 01 c8 [ ]*monitor %ax,%ecx,%edx
+  70: 67 0f 01 c8 [ ]*monitor %ax,%ecx,%edx
  ...
--- binutils/gas/testsuite/gas/i386/prescott.s.pni 2004-06-23 08:06:58.000000000 -0700
+++ binutils/gas/testsuite/gas/i386/prescott.s 2005-12-05 14:29:59.000000000 -0800
@@ -29,4 +29,7 @@ foo:
  mwait
  mwait %eax,%ecx
 
+ monitor %ax,%ecx,%edx
+ addr16 monitor
+
  .p2align 4,0
--- binutils/gas/testsuite/gas/i386/x86-64-prescott.d.pni 2005-12-05 14:29:59.000000000 -0800
+++ binutils/gas/testsuite/gas/i386/x86-64-prescott.d 2005-12-05 14:29:59.000000000 -0800
@@ -0,0 +1,37 @@
+#objdump: -dw
+#name: x86-64 prescott
+
+.*: +file format .*
+
+Disassembly of section .text:
+
+0+000 <foo>:
+   0: 66 0f d0 01 [ ]*addsubpd \(%rcx\),%xmm0
+   4: 66 0f d0 ca [ ]*addsubpd %xmm2,%xmm1
+   8: f2 0f d0 13 [ ]*addsubps \(%rbx\),%xmm2
+   c: f2 0f d0 dc [ ]*addsubps %xmm4,%xmm3
+  10: df 88 90 90 90 90 [ ]*fisttp 0xffffffff90909090\(%rax\)
+  16: db 88 90 90 90 90 [ ]*fisttpl 0xffffffff90909090\(%rax\)
+  1c: dd 88 90 90 90 90 [ ]*fisttpll 0xffffffff90909090\(%rax\)
+  22: 66 0f 7c 65 00 [ ]*haddpd 0x0\(%rbp\),%xmm4
+  27: 66 0f 7c ee [ ]*haddpd %xmm6,%xmm5
+  2b: f2 0f 7c 37 [ ]*haddps \(%rdi\),%xmm6
+  2f: f2 0f 7c f8 [ ]*haddps %xmm0,%xmm7
+  33: 66 0f 7d c1 [ ]*hsubpd %xmm1,%xmm0
+  37: 66 0f 7d 0a [ ]*hsubpd \(%rdx\),%xmm1
+  3b: f2 0f 7d d2 [ ]*hsubps %xmm2,%xmm2
+  3f: f2 0f 7d 1c 24 [ ]*hsubps \(%rsp\),%xmm3
+  44: f2 0f f0 2e [ ]*lddqu  \(%rsi\),%xmm5
+  48: 0f 01 c8 [ ]*monitor %rax,%rcx,%rdx
+  4b: 0f 01 c8 [ ]*monitor %rax,%rcx,%rdx
+  4e: f2 0f 12 f7 [ ]*movddup %xmm7,%xmm6
+  52: f2 0f 12 38 [ ]*movddup \(%rax\),%xmm7
+  56: f3 0f 16 01 [ ]*movshdup \(%rcx\),%xmm0
+  5a: f3 0f 16 ca [ ]*movshdup %xmm2,%xmm1
+  5e: f3 0f 12 13 [ ]*movsldup \(%rbx\),%xmm2
+  62: f3 0f 12 dc [ ]*movsldup %xmm4,%xmm3
+  66: 0f 01 c9 [ ]*mwait  %rax,%rcx
+  69: 0f 01 c9 [ ]*mwait  %rax,%rcx
+  6c: 67 0f 01 c8 [ ]*monitor %eax,%rcx,%rdx
+  70: 67 0f 01 c8 [ ]*monitor %eax,%rcx,%rdx
+ ...
--- binutils/gas/testsuite/gas/i386/x86-64-prescott.s.pni 2005-12-05 14:29:59.000000000 -0800
+++ binutils/gas/testsuite/gas/i386/x86-64-prescott.s 2005-12-05 14:29:59.000000000 -0800
@@ -0,0 +1,35 @@
+#Prescott New Instructions
+
+ .text
+foo:
+ addsubpd (%rcx),%xmm0
+ addsubpd %xmm2,%xmm1
+ addsubps (%rbx),%xmm2
+ addsubps %xmm4,%xmm3
+ fisttp 0x90909090(%rax)
+ fisttpl 0x90909090(%rax)
+ fisttpll 0x90909090(%rax)
+ haddpd 0x0(%rbp),%xmm4
+ haddpd %xmm6,%xmm5
+ haddps (%rdi),%xmm6
+ haddps %xmm0,%xmm7
+ hsubpd %xmm1,%xmm0
+ hsubpd (%rdx),%xmm1
+ hsubps %xmm2,%xmm2
+ hsubps (%rsp,1),%xmm3
+ lddqu (%rsi),%xmm5
+ monitor
+ monitor %rax,%rcx,%rdx
+ movddup %xmm7,%xmm6
+ movddup (%rax),%xmm7
+ movshdup (%rcx),%xmm0
+ movshdup %xmm2,%xmm1
+ movsldup (%rbx),%xmm2
+ movsldup %xmm4,%xmm3
+ mwait
+ mwait %rax,%rcx
+
+ monitor %eax,%rcx,%rdx
+ addr32 monitor
+
+ .p2align 4,0
--- binutils/include/opcode/i386.h.pni 2005-07-27 08:41:15.000000000 -0700
+++ binutils/include/opcode/i386.h 2005-12-05 14:29:59.000000000 -0800
@@ -1346,14 +1346,24 @@ static const template i386_optab[] =
 {"hsubps",    2, 0xf20f7d,  X, CpuPNI, NoSuf|IgnoreSize|Modrm, { RegXMM|LLongMem, RegXMM, 0 } },
 {"lddqu",     2, 0xf20ff0,  X, CpuPNI, NoSuf|IgnoreSize|Modrm, { LLongMem, RegXMM, 0 } },
 {"monitor",   0, 0x0f01, 0xc8, CpuPNI, NoSuf|ImmExt, { 0, 0, 0} },
-/* Need to ensure only "monitor %eax,%ecx,%edx" is accepted. */
-{"monitor",   3, 0x0f01, 0xc8, CpuPNI, NoSuf|ImmExt, { Reg32, Reg32, Reg32} },
+/* monitor is very special. CX and DX are always 64bits with zero upper
+   32bits in 64bit mode, and 32bits in 16bit and 32bit modes. The
+   address size override prefix can be used to overrride the AX size in
+   all modes.  */
+/* Need to ensure only "monitor %eax/%ax,%ecx,%edx" is accepted. */
+{"monitor",   3, 0x0f01, 0xc8, CpuPNI|CpuNo64, NoSuf|ImmExt, { Reg16|Reg32, Reg32, Reg32 } },
+/* Need to ensure only "monitor %rax/%eax,%rcx,%rdx" is accepted. */
+{"monitor",   3, 0x0f01, 0xc8, CpuPNI|Cpu64, NoSuf|ImmExt|NoRex64, { Reg32|Reg64, Reg64, Reg64 } },
 {"movddup",   2, 0xf20f12,  X, CpuPNI, NoSuf|IgnoreSize|Modrm, { RegXMM|LLongMem, RegXMM, 0 } },
 {"movshdup",  2, 0xf30f16,  X, CpuPNI, NoSuf|IgnoreSize|Modrm, { RegXMM|LLongMem, RegXMM, 0 } },
 {"movsldup",  2, 0xf30f12,  X, CpuPNI, NoSuf|IgnoreSize|Modrm, { RegXMM|LLongMem, RegXMM, 0 } },
 {"mwait",     0, 0x0f01, 0xc9, CpuPNI, NoSuf|ImmExt, { 0, 0, 0} },
+/* mwait is very special. AX and CX are always 64bits with zero upper
+   32bits in 64bit mode, and 32bits in 16bit and 32bit modes.  */
 /* Need to ensure only "mwait %eax,%ecx" is accepted.  */
-{"mwait",     2, 0x0f01, 0xc9, CpuPNI, NoSuf|ImmExt, { Reg32, Reg32, 0} },
+{"mwait",     2, 0x0f01, 0xc9, CpuPNI|CpuNo64, NoSuf|ImmExt, { Reg32, Reg32, 0} },
+/* Need to ensure only "mwait %rax,%rcx" is accepted.  */
+{"mwait",     2, 0x0f01, 0xc9, CpuPNI|Cpu64, NoSuf|ImmExt|NoRex64, { Reg64, Reg64, 0} },
 
 /* VMX instructions.  */
 {"vmcall",    0, 0x0f01, 0xc1, CpuVMX, NoSuf|ImmExt, { 0, 0, 0} },
--- binutils/opcodes/i386-dis.c.pni 2005-11-11 10:48:50.000000000 -0800
+++ binutils/opcodes/i386-dis.c 2005-12-05 15:17:00.000000000 -0800
@@ -115,8 +115,14 @@ struct dis_private {
    when we can.  */
 #define FWAIT_OPCODE (0x9b)
 
-/* Set to 1 for 64bit mode disassembly.  */
-static int mode_64bit;
+enum address_mode
+{
+  mode_16bit,
+  mode_32bit,
+  mode_64bit
+};
+
+enum address_mode address_mode;
 
 /* Flags for the prefixes for the current instruction.  See below.  */
 static int prefixes;
@@ -1772,7 +1778,7 @@ ckprefix (void)
  case 0x4d:
  case 0x4e:
  case 0x4f:
-    if (mode_64bit)
+    if (address_mode == mode_64bit)
       newrex = *codep;
     else
       return;
@@ -1898,7 +1904,7 @@ prefix_name (int pref, int sizeflag)
     case 0x66:
       return (sizeflag & DFLAG) ? "data16" : "data32";
     case 0x67:
-      if (mode_64bit)
+      if (address_mode == mode_64bit)
  return (sizeflag & AFLAG) ? "addr32" : "addr64";
       else
  return (sizeflag & AFLAG) ? "addr16" : "addr32";
@@ -1970,8 +1976,11 @@ print_insn (bfd_vma pc, disassemble_info
   const char *p;
   struct dis_private priv;
 
-  mode_64bit = (info->mach == bfd_mach_x86_64_intel_syntax
- || info->mach == bfd_mach_x86_64);
+  if (info->mach == bfd_mach_x86_64_intel_syntax
+      || info->mach == bfd_mach_x86_64)
+    address_mode = mode_64bit;
+  else
+    address_mode = mode_32bit;
 
   if (intel_syntax == (char) -1)
     intel_syntax = (info->mach == bfd_mach_i386_i386_intel_syntax
@@ -1991,17 +2000,17 @@ print_insn (bfd_vma pc, disassemble_info
     {
       if (strncmp (p, "x86-64", 6) == 0)
  {
-  mode_64bit = 1;
+  address_mode = mode_64bit;
   priv.orig_sizeflag = AFLAG | DFLAG;
  }
       else if (strncmp (p, "i386", 4) == 0)
  {
-  mode_64bit = 0;
+  address_mode = mode_32bit;
   priv.orig_sizeflag = AFLAG | DFLAG;
  }
       else if (strncmp (p, "i8086", 5) == 0)
  {
-  mode_64bit = 0;
+  address_mode = mode_16bit;
   priv.orig_sizeflag = 0;
  }
       else if (strncmp (p, "intel", 5) == 0)
@@ -2170,7 +2179,7 @@ print_insn (bfd_vma pc, disassemble_info
       sizeflag ^= AFLAG;
       if (dp->bytemode3 != loop_jcxz_mode || intel_syntax)
  {
-  if ((sizeflag & AFLAG) || mode_64bit)
+  if ((sizeflag & AFLAG) || address_mode == mode_64bit)
     oappend ("addr32 ");
   else
     oappend ("addr16 ");
@@ -2237,7 +2246,8 @@ print_insn (bfd_vma pc, disassemble_info
       break;
 
     case X86_64_SPECIAL:
-      dp = &x86_64_table[dp->bytemode2][mode_64bit];
+      index = address_mode == mode_64bit ? 1 : 0;
+      dp = &x86_64_table[dp->bytemode2][index];
       break;
 
     default:
@@ -2739,7 +2749,7 @@ putop (const char *template, int sizefla
   alt = 0;
   if (intel_syntax)
     alt += 1;
-  if (mode_64bit)
+  if (address_mode == mode_64bit)
     alt += 2;
   while (alt != 0)
     {
@@ -2795,7 +2805,7 @@ putop (const char *template, int sizefla
     }
   break;
  case 'E': /* For jcxz/jecxz */
-  if (mode_64bit)
+  if (address_mode == mode_64bit)
     {
       if (sizeflag & AFLAG)
  *obufp++ = 'r';
@@ -2813,9 +2823,9 @@ putop (const char *template, int sizefla
   if ((prefixes & PREFIX_ADDR) || (sizeflag & SUFFIX_ALWAYS))
     {
       if (sizeflag & AFLAG)
- *obufp++ = mode_64bit ? 'q' : 'l';
+ *obufp++ = address_mode == mode_64bit ? 'q' : 'l';
       else
- *obufp++ = mode_64bit ? 'l' : 'w';
+ *obufp++ = address_mode == mode_64bit ? 'l' : 'w';
       used_prefixes |= (prefixes & PREFIX_ADDR);
     }
   break;
@@ -2861,7 +2871,7 @@ putop (const char *template, int sizefla
  case 'T':
   if (intel_syntax)
     break;
-  if (mode_64bit && (sizeflag & DFLAG))
+  if (address_mode == mode_64bit && (sizeflag & DFLAG))
     {
       *obufp++ = 'q';
       break;
@@ -2890,7 +2900,7 @@ putop (const char *template, int sizefla
  case 'U':
   if (intel_syntax)
     break;
-  if (mode_64bit && (sizeflag & DFLAG))
+  if (address_mode == mode_64bit && (sizeflag & DFLAG))
     {
       if (mod != 3 || (sizeflag & SUFFIX_ALWAYS))
  *obufp++ = 'q';
@@ -2950,7 +2960,7 @@ putop (const char *template, int sizefla
  case 'V':
   if (intel_syntax)
     break;
-  if (mode_64bit && (sizeflag & DFLAG))
+  if (address_mode == mode_64bit && (sizeflag & DFLAG))
     {
       if (sizeflag & SUFFIX_ALWAYS)
  *obufp++ = 'q';
@@ -3080,7 +3090,7 @@ OP_indirE (int bytemode, int sizeflag)
 static void
 print_operand_value (char *buf, int hex, bfd_vma disp)
 {
-  if (mode_64bit)
+  if (address_mode == mode_64bit)
     {
       if (hex)
  {
@@ -3147,7 +3157,7 @@ intel_operand_size (int bytemode, int si
       oappend ("WORD PTR ");
       break;
     case stack_v_mode:
-      if (mode_64bit && (sizeflag & DFLAG))
+      if (address_mode == mode_64bit && (sizeflag & DFLAG))
  {
   oappend ("QWORD PTR ");
   used_prefixes |= (prefixes & PREFIX_DATA);
@@ -3172,7 +3182,7 @@ intel_operand_size (int bytemode, int si
       oappend ("QWORD PTR ");
       break;
     case m_mode:
-      if (mode_64bit)
+      if (address_mode == mode_64bit)
  oappend ("QWORD PTR ");
       else
  oappend ("DWORD PTR ");
@@ -3230,13 +3240,13 @@ OP_E (int bytemode, int sizeflag)
   oappend (names64[rm + add]);
   break;
  case m_mode:
-  if (mode_64bit)
+  if (address_mode == mode_64bit)
     oappend (names64[rm + add]);
   else
     oappend (names32[rm + add]);
   break;
  case stack_v_mode:
-  if (mode_64bit && (sizeflag & DFLAG))
+  if (address_mode == mode_64bit && (sizeflag & DFLAG))
     {
       oappend (names64[rm + add]);
       used_prefixes |= (prefixes & PREFIX_DATA);
@@ -3270,7 +3280,7 @@ OP_E (int bytemode, int sizeflag)
     intel_operand_size (bytemode, sizeflag);
   append_seg ();
 
-  if ((sizeflag & AFLAG) || mode_64bit) /* 32 bit address mode */
+  if ((sizeflag & AFLAG) || address_mode == mode_64bit) /* 32 bit address mode */
     {
       int havesib;
       int havebase;
@@ -3287,7 +3297,7 @@ OP_E (int bytemode, int sizeflag)
   havesib = 1;
   FETCH_DATA (the_info, codep + 1);
   index = (*codep >> 3) & 7;
-  if (mode_64bit || index != 0x4)
+  if (address_mode == mode_64bit || index != 0x4)
     /* When INDEX == 0x4 in 32 bit mode, SCALE is ignored.  */
     scale = (*codep >> 6) & 3;
   base = *codep & 7;
@@ -3304,7 +3314,7 @@ OP_E (int bytemode, int sizeflag)
   if ((base & 7) == 5)
     {
       havebase = 0;
-      if (mode_64bit && !havesib)
+      if (address_mode == mode_64bit && !havesib)
  riprel = 1;
       disp = get32s ();
     }
@@ -3339,7 +3349,7 @@ OP_E (int bytemode, int sizeflag)
     oappend ("rip + ");
   *obufp = '\0';
   if (havebase)
-    oappend (mode_64bit && (sizeflag & AFLAG)
+    oappend (address_mode == mode_64bit && (sizeflag & AFLAG)
      ? names64[base] : names32[base]);
   if (havesib)
     {
@@ -3350,7 +3360,7 @@ OP_E (int bytemode, int sizeflag)
       *obufp++ = separator_char;
       *obufp = '\0';
     }
-  oappend (mode_64bit && (sizeflag & AFLAG)
+  oappend (address_mode == mode_64bit && (sizeflag & AFLAG)
    ? names64[index] : names32[index]);
  }
       if (scale != 0 || (!intel_syntax && index != 4))
@@ -3511,7 +3521,7 @@ OP_G (int bytemode, int sizeflag)
       used_prefixes |= (prefixes & PREFIX_DATA);
       break;
     case m_mode:
-      if (mode_64bit)
+      if (address_mode == mode_64bit)
  oappend (names64[reg + add]);
       else
  oappend (names32[reg + add]);
@@ -3591,7 +3601,7 @@ static void
 set_op (bfd_vma op, int riprel)
 {
   op_index[op_ad] = op_ad;
-  if (mode_64bit)
+  if (address_mode == mode_64bit)
     {
       op_address[op_ad] = op;
       op_riprel[op_ad] = riprel;
@@ -3639,7 +3649,7 @@ OP_REG (int code, int sizeflag)
       break;
     case rAX_reg: case rCX_reg: case rDX_reg: case rBX_reg:
     case rSP_reg: case rBP_reg: case rSI_reg: case rDI_reg:
-      if (mode_64bit && (sizeflag & DFLAG))
+      if (address_mode == mode_64bit && (sizeflag & DFLAG))
  {
   s = names64[code - rAX_reg + add];
   break;
@@ -3725,7 +3735,7 @@ OP_I (int bytemode, int sizeflag)
       mask = 0xff;
       break;
     case q_mode:
-      if (mode_64bit)
+      if (address_mode == mode_64bit)
  {
   op = get32s ();
   break;
@@ -3773,7 +3783,7 @@ OP_I64 (int bytemode, int sizeflag)
   bfd_signed_vma op;
   bfd_signed_vma mask = -1;
 
-  if (!mode_64bit)
+  if (address_mode != mode_64bit)
     {
       OP_I (bytemode, sizeflag);
       return;
@@ -3941,7 +3951,7 @@ OP_OFF (int bytemode, int sizeflag)
     intel_operand_size (bytemode, sizeflag);
   append_seg ();
 
-  if ((sizeflag & AFLAG) || mode_64bit)
+  if ((sizeflag & AFLAG) || address_mode == mode_64bit)
     off = get32 ();
   else
     off = get16 ();
@@ -3964,7 +3974,7 @@ OP_OFF64 (int bytemode, int sizeflag)
 {
   bfd_vma off;
 
-  if (!mode_64bit)
+  if (address_mode != mode_64bit)
     {
       OP_OFF (bytemode, sizeflag);
       return;
@@ -3996,7 +4006,7 @@ ptr_reg (int code, int sizeflag)
 
   *obufp++ = open_char;
   used_prefixes |= (prefixes & PREFIX_ADDR);
-  if (mode_64bit)
+  if (address_mode == mode_64bit)
     {
       if (!(sizeflag & AFLAG))
  s = names32[code - eAX_reg];
@@ -4050,7 +4060,7 @@ OP_C (int dummy ATTRIBUTE_UNUSED, int si
       USED_REX (REX_EXTX);
       add = 8;
     }
-  else if (!mode_64bit && (prefixes & PREFIX_LOCK))
+  else if (address_mode != mode_64bit && (prefixes & PREFIX_LOCK))
     {
       used_prefixes |= PREFIX_LOCK;
       add = 8;
@@ -4412,18 +4422,31 @@ PNI_Fixup (int extrachar ATTRIBUTE_UNUSE
   if (mod == 3 && reg == 1 && rm <= 1)
     {
       /* Override "sidt".  */
-      char *p = obuf + strlen (obuf) - 4;
+      size_t olen = strlen (obuf);
+      char *p = obuf + olen - 4;
+      const char **names = (address_mode == mode_64bit
+    ? names64 : names32);
 
       /* We might have a suffix when disassembling with -Msuffix.  */
       if (*p == 'i')
  --p;
 
+      /* Remove "addr16/addr32" if we aren't in Intel mode.  */
+      if (!intel_syntax
+  && (prefixes & PREFIX_ADDR)
+  && olen >= (4 + 7)
+  && *(p - 1) == ' '
+  && strncmp (p - 7, "addr", 4) == 0
+  && (strncmp (p - 3, "16", 2) == 0
+      || strncmp (p - 3, "32", 2) == 0))
+ p -= 7;
+
       if (rm)
  {
   /* mwait %eax,%ecx  */
   strcpy (p, "mwait");
   if (!intel_syntax)
-    strcpy (op1out, names32[0]);
+    strcpy (op1out, names[0]);
  }
       else
  {
@@ -4431,21 +4454,23 @@ PNI_Fixup (int extrachar ATTRIBUTE_UNUSE
   strcpy (p, "monitor");
   if (!intel_syntax)
     {
-      if (!mode_64bit)
- strcpy (op1out, names32[0]);
-      else if (!(prefixes & PREFIX_ADDR))
- strcpy (op1out, names64[0]);
+      const char **op1_names;
+      if (!(prefixes & PREFIX_ADDR))
+ op1_names = (address_mode == mode_16bit
+     ? names16 : names);
       else
  {
-  strcpy (op1out, names32[0]);
+  op1_names = (address_mode != mode_32bit
+       ? names32 : names16);
   used_prefixes |= PREFIX_ADDR;
  }
-      strcpy (op3out, names32[2]);
+      strcpy (op1out, op1_names[0]);
+      strcpy (op3out, names[2]);
     }
  }
       if (!intel_syntax)
  {
-  strcpy (op2out, names32[1]);
+  strcpy (op2out, names[1]);
   two_source_ops = 1;
  }
 
@@ -4513,7 +4538,7 @@ SVME_Fixup (int bytemode, int sizeflag)
     case 0xda:
     case 0xdb:
       *obufp++ = open_char;
-      if (mode_64bit || (sizeflag & AFLAG))
+      if (address_mode == mode_64bit || (sizeflag & AFLAG))
         alt = names32[0];
       else
         alt = names16[0];