qemu-devel.nongnu.org archive mirror
 help / color / mirror / Atom feed
* [Qemu-devel] [PATCH] i386/translate: ignore 0x67 (PREFIX_ADR) on TARGET_X86_64 && CODE64()
@ 2013-05-24 21:37 Laszlo Ersek
  2013-05-25 23:23 ` Richard Henderson
  0 siblings, 1 reply; 5+ messages in thread
From: Laszlo Ersek @ 2013-05-24 21:37 UTC (permalink / raw)
  To: Richard Henderson, qemu-devel

The code reorganization in commit 4a6fd938 broke handling of PREFIX_ADR.
Restore the previous behavior:

If TARGET_X86_64 *and* CODE64():
  (a) PREFIX_ADR set: no effect, "aflag" should stay at the original
      "s->code32" value,
  (b) PREFIX_ADR clear: "aflag" should be set to constant 2.

Otherwise:
  (c) PREFIX_ADR set: the least significant bit in "aflag" (originally
      initialized form "s->code32") should be negated,
  (d) PREFIX_ADR clear: no effect, "aflag" should stay at the original
      "s->code32" value.

Currently branch (a) is mishandled as branch (c).

Please-review: Richard Henderson <rth@twiddle.net>
Signed-off-by: Laszlo Ersek <lersek@redhat.com>
---
 target-i386/translate.c |    6 +++++-
 1 files changed, 5 insertions(+), 1 deletions(-)

diff --git a/target-i386/translate.c b/target-i386/translate.c
index 0aeccdb..86f2678 100644
--- a/target-i386/translate.c
+++ b/target-i386/translate.c
@@ -4813,7 +4813,11 @@ static target_ulong disas_insn(CPUX86State *env, DisasContext *s,
             /* 0x66 is ignored if rex.w is set */
             dflag = 2;
         }
-        if (!(prefixes & PREFIX_ADR)) {
+        if (prefixes & PREFIX_ADR) {
+            /* flip it back, 0x67 should have no effect */
+            aflag ^= 1;
+        }
+        else {
             aflag = 2;
         }
     }
-- 
1.7.1

^ permalink raw reply related	[flat|nested] 5+ messages in thread

* Re: [Qemu-devel] [PATCH] i386/translate: ignore 0x67 (PREFIX_ADR) on TARGET_X86_64 && CODE64()
  2013-05-24 21:37 [Qemu-devel] [PATCH] i386/translate: ignore 0x67 (PREFIX_ADR) on TARGET_X86_64 && CODE64() Laszlo Ersek
@ 2013-05-25 23:23 ` Richard Henderson
  2013-05-26  8:33   ` Paolo Bonzini
  0 siblings, 1 reply; 5+ messages in thread
From: Richard Henderson @ 2013-05-25 23:23 UTC (permalink / raw)
  To: Laszlo Ersek; +Cc: qemu-devel

On 2013-05-24 14:37, Laszlo Ersek wrote:
> @@ -4813,7 +4813,11 @@ static target_ulong disas_insn(CPUX86State *env, DisasContext *s,
>               /* 0x66 is ignored if rex.w is set */
>               dflag = 2;
>           }
> -        if (!(prefixes & PREFIX_ADR)) {
> +        if (prefixes & PREFIX_ADR) {
> +            /* flip it back, 0x67 should have no effect */
> +            aflag ^= 1;
> +        }
> +        else {
>               aflag = 2;
>           }
>       }
>

Agreed that there's a bug here.  I'm thinking it would be clearer to not write 
this as yet another flip, but understand that unlike dflag, aflag can only be
either 1 or 2 in 64-bit mode.

I'm thinking of something more like this:


r~


diff --git a/target-i386/translate.c b/target-i386/translate.c
index 0aeccdb..bf772aa 100644
--- a/target-i386/translate.c
+++ b/target-i386/translate.c
@@ -4813,9 +4813,8 @@ static target_ulong disas_insn(CPUX86State *env, 
DisasContext *s,
              /* 0x66 is ignored if rex.w is set */
              dflag = 2;
          }
-        if (!(prefixes & PREFIX_ADR)) {
-            aflag = 2;
-        }
+        /* 0x67 toggles between 64-bit and 32-bit addressing.  */
+        aflag = (prefixes & PREFIX_ADR ? 1 : 2);
      }
  #endif

^ permalink raw reply related	[flat|nested] 5+ messages in thread

* Re: [Qemu-devel] [PATCH] i386/translate: ignore 0x67 (PREFIX_ADR) on TARGET_X86_64 && CODE64()
  2013-05-25 23:23 ` Richard Henderson
@ 2013-05-26  8:33   ` Paolo Bonzini
  2013-05-26 23:45     ` Laszlo Ersek
  0 siblings, 1 reply; 5+ messages in thread
From: Paolo Bonzini @ 2013-05-26  8:33 UTC (permalink / raw)
  To: Richard Henderson; +Cc: Laszlo Ersek, qemu-devel

Il 26/05/2013 01:23, Richard Henderson ha scritto:
> On 2013-05-24 14:37, Laszlo Ersek wrote:
>> @@ -4813,7 +4813,11 @@ static target_ulong disas_insn(CPUX86State
>> *env, DisasContext *s,
>>               /* 0x66 is ignored if rex.w is set */
>>               dflag = 2;
>>           }
>> -        if (!(prefixes & PREFIX_ADR)) {
>> +        if (prefixes & PREFIX_ADR) {
>> +            /* flip it back, 0x67 should have no effect */
>> +            aflag ^= 1;
>> +        }
>> +        else {
>>               aflag = 2;
>>           }
>>       }
>>
> 
> Agreed that there's a bug here.  I'm thinking it would be clearer to not
> write this as yet another flip, but understand that unlike dflag, aflag
> can only be either 1 or 2 in 64-bit mode.
> 
> I'm thinking of something more like this:
> 
> diff --git a/target-i386/translate.c b/target-i386/translate.c
> index 0aeccdb..bf772aa 100644
> --- a/target-i386/translate.c
> +++ b/target-i386/translate.c
> @@ -4813,9 +4813,8 @@ static target_ulong disas_insn(CPUX86State *env,
> DisasContext *s,
>              /* 0x66 is ignored if rex.w is set */
>              dflag = 2;
>          }
> -        if (!(prefixes & PREFIX_ADR)) {
> -            aflag = 2;
> -        }
> +        /* 0x67 toggles between 64-bit and 32-bit addressing.  */
> +        aflag = (prefixes & PREFIX_ADR ? 1 : 2);

Isn't that just "aflag++"?  Needs a comment of course ("toggle between
32- and 64-bit, not 16- and 32-bit.").

Paolo

^ permalink raw reply	[flat|nested] 5+ messages in thread

* Re: [Qemu-devel] [PATCH] i386/translate: ignore 0x67 (PREFIX_ADR) on TARGET_X86_64 && CODE64()
  2013-05-26  8:33   ` Paolo Bonzini
@ 2013-05-26 23:45     ` Laszlo Ersek
  2013-05-27  6:29       ` Paolo Bonzini
  0 siblings, 1 reply; 5+ messages in thread
From: Laszlo Ersek @ 2013-05-26 23:45 UTC (permalink / raw)
  To: Paolo Bonzini; +Cc: qemu-devel, Richard Henderson

On 05/26/13 10:33, Paolo Bonzini wrote:
> Il 26/05/2013 01:23, Richard Henderson ha scritto:
>> On 2013-05-24 14:37, Laszlo Ersek wrote:
>>> @@ -4813,7 +4813,11 @@ static target_ulong disas_insn(CPUX86State
>>> *env, DisasContext *s,
>>>               /* 0x66 is ignored if rex.w is set */
>>>               dflag = 2;
>>>           }
>>> -        if (!(prefixes & PREFIX_ADR)) {
>>> +        if (prefixes & PREFIX_ADR) {
>>> +            /* flip it back, 0x67 should have no effect */
>>> +            aflag ^= 1;
>>> +        }
>>> +        else {
>>>               aflag = 2;
>>>           }
>>>       }
>>>
>>
>> Agreed that there's a bug here.  I'm thinking it would be clearer to not
>> write this as yet another flip, but understand that unlike dflag, aflag
>> can only be either 1 or 2 in 64-bit mode.
>>
>> I'm thinking of something more like this:
>>
>> diff --git a/target-i386/translate.c b/target-i386/translate.c
>> index 0aeccdb..bf772aa 100644
>> --- a/target-i386/translate.c
>> +++ b/target-i386/translate.c
>> @@ -4813,9 +4813,8 @@ static target_ulong disas_insn(CPUX86State *env,
>> DisasContext *s,
>>              /* 0x66 is ignored if rex.w is set */
>>              dflag = 2;
>>          }
>> -        if (!(prefixes & PREFIX_ADR)) {
>> -            aflag = 2;
>> -        }
>> +        /* 0x67 toggles between 64-bit and 32-bit addressing.  */
>> +        aflag = (prefixes & PREFIX_ADR ? 1 : 2);
> 
> Isn't that just "aflag++"?  Needs a comment of course ("toggle between
> 32- and 64-bit, not 16- and 32-bit.").

I finally looked up in the SDM what the 0x67 (address-size override)
prefix does. Apparently,

  2.1.1 Instruction Prefixes

    [...] The address-size override prefix (67H) allows programs to
    switch between 16- and 32-bit addressing. Either size can be the
    default; the prefix selects the non-default size. [...]

  CMPS/CMPSB/CMPSW/CMPSD/CMPSQ -- Compare String Operands

    [...] In 64-bit mode, the instruction's default address size is 64
    bits, 32 bit address size is supported using the prefix 67H. [...]

Assuming that
- aflag==0 means 16-bit address,
- aflag==1 means 32-bit address,
- aflag==2 means 64-bit address,
- and bit0 in "s->code32" carries "aflag" corresponding to the default
  address size in 32-bit mode,

I think Richard's patch is correct (my approach was only to restore the
pre-patch logic without having any clue about the variables' contents).

I believe aflag++ is incorrect if the current default address size for
32-bit is 16-bit (ie. (s->code32 & 1) == 0). In this case the first XOR
(seeing the 0x67 prefix) flips it to 1, and the increment would change
it to 2. aflag==2 corresponds to 64-bit address, but in 64-bit mode with
the 0x67 prefix we must choose 32-bit.

(IOW in 32-bit mode the meaning of the 0x67 prefix is not absolute but
relative.)

Laszlo

^ permalink raw reply	[flat|nested] 5+ messages in thread

* Re: [Qemu-devel] [PATCH] i386/translate: ignore 0x67 (PREFIX_ADR) on TARGET_X86_64 && CODE64()
  2013-05-26 23:45     ` Laszlo Ersek
@ 2013-05-27  6:29       ` Paolo Bonzini
  0 siblings, 0 replies; 5+ messages in thread
From: Paolo Bonzini @ 2013-05-27  6:29 UTC (permalink / raw)
  To: Laszlo Ersek; +Cc: qemu-devel, Richard Henderson

Il 27/05/2013 01:45, Laszlo Ersek ha scritto:
> I believe aflag++ is incorrect if the current default address size for
> 32-bit is 16-bit (ie. (s->code32 & 1) == 0).

... which cannot happen. :)

(Sorry, should have been more verbose).

See cpu_x86_load_seg_cache:

#ifdef TARGET_X86_64
            if ((env->hflags & HF_LMA_MASK) && (flags & DESC_L_MASK)) {
                /* long mode */
                env->hflags |= HF_CS32_MASK | HF_SS32_MASK | HF_CS64_MASK;
                env->hflags &= ~(HF_ADDSEG_MASK);
            } else
#endif
            {
                /* legacy / compatibility case */
                new_hflags = (env->segs[R_CS].flags & DESC_B_MASK)
                    >> (DESC_B_SHIFT - HF_CS32_SHIFT);
                env->hflags = (env->hflags & ~(HF_CS32_MASK | HF_CS64_MASK)) |
                    new_hflags;
            }

This is the only place where HF_CS64_MASK is added to env->hflags.  Then:

    dc->code64 = (flags >> HF_CS64_SHIFT) & 1;

#define CODE64(s) ((s)->code64)

Paolo

 In this case the first XOR
> (seeing the 0x67 prefix) flips it to 1, and the increment would change
> it to 2. aflag==2 corresponds to 64-bit address, but in 64-bit mode with
> the 0x67 prefix we must choose 32-bit.
> 
> (IOW in 32-bit mode the meaning of the 0x67 prefix is not absolute but
> relative.)
> 
> Laszlo
> 
> 

^ permalink raw reply	[flat|nested] 5+ messages in thread

end of thread, other threads:[~2013-05-27  6:29 UTC | newest]

Thread overview: 5+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2013-05-24 21:37 [Qemu-devel] [PATCH] i386/translate: ignore 0x67 (PREFIX_ADR) on TARGET_X86_64 && CODE64() Laszlo Ersek
2013-05-25 23:23 ` Richard Henderson
2013-05-26  8:33   ` Paolo Bonzini
2013-05-26 23:45     ` Laszlo Ersek
2013-05-27  6:29       ` Paolo Bonzini

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).